bool FArchiveFileReaderGeneric::InternalPrecache( int64 PrecacheOffset, int64 PrecacheSize )
{
	// Only precache at current position and avoid work if precaching same offset twice.
	if( Pos == PrecacheOffset &&( !BufferBase || !BufferCount || BufferBase != Pos ) )
	{
		BufferBase = Pos;
		BufferCount = FMath::Min( FMath::Min( PrecacheSize,( int64 )( ARRAY_COUNT( Buffer ) -( Pos&( ARRAY_COUNT( Buffer )-1 ) ) ) ), Size-Pos );
		BufferCount = FMath::Max( BufferCount, 0LL ); // clamp to 0
		int64 Count = 0;

		// Read data from device via Win32 ReadFile API.
		{
			UE_CLOG( BufferCount > ARRAY_COUNT( Buffer ) || BufferCount <= 0, LogFileManager, Fatal, TEXT("Invalid BufferCount=%lld while reading %s. File is most likely corrupted, try deleting it if possible. Pos=%lld, Size=%lld, PrecacheSize=%lld, PrecacheOffset=%lld"),
				BufferCount, *Filename, Pos, Size, PrecacheSize, PrecacheOffset );

			ReadLowLevel( Buffer, BufferCount, Count );
		}

		if( Count!=BufferCount )
		{
			TCHAR ErrorBuffer[1024];
			ArIsError = true;
			UE_LOG( LogFileManager, Warning, TEXT( "ReadFile failed: Count=%lld BufferCount=%lld Error=%s" ), Count, BufferCount, FPlatformMisc::GetSystemErrorMessage( ErrorBuffer, 1024, 0 ) );
		}
	}
	return true;
}
Esempio n. 2
0
bool UObjectBaseUtility::IsA( const UClass* SomeBase ) const
{
	UE_CLOG(!SomeBase, LogObj, Fatal, TEXT("IsA(NULL) cannot yield meaningful results"));

	#if UCLASS_FAST_ISA_IMPL & 1
		bool bOldResult = false;
		for ( UClass* TempClass=GetClass(); TempClass; TempClass=TempClass->GetSuperClass() )
		{
			if ( TempClass == SomeBase )
			{
				bOldResult = true;
				break;
			}
		}
	#endif

	#if UCLASS_FAST_ISA_IMPL & 2
		bool bNewResult = GetClass()->IsAUsingFastTree(*SomeBase);
	#endif

	#if (UCLASS_FAST_ISA_IMPL & 1) && (UCLASS_FAST_ISA_IMPL & 2)
		ensureMsgf(bOldResult == bNewResult, TEXT("New cast code failed"));
	#endif

	#if UCLASS_FAST_ISA_IMPL & 1
		return bOldResult;
	#else
		return bNewResult;
	#endif
}
Esempio n. 3
0
void UObject::SetLinker( FLinkerLoad* LinkerLoad, int32 LinkerIndex, bool bShouldDetachExisting )
{
	FLinkerIndexPair Existing = LinkerAnnotation.GetAnnotation(this);
	Existing.CheckInvariants();
	// Detach from existing linker.
	if( Existing.Linker && bShouldDetachExisting )
	{
		checkf(!HasAnyFlags(RF_NeedLoad|RF_NeedPostLoad), TEXT("Detaching from existing linker for %s while object %s needs loaded"), *Existing.Linker->GetArchiveName(), *GetFullName());
		check(Existing.Linker->ExportMap[Existing.LinkerIndex].Object!=NULL);
		check(Existing.Linker->ExportMap[Existing.LinkerIndex].Object==this);
		Existing.Linker->ExportMap[Existing.LinkerIndex].Object = NULL;
	}

	if (Existing.Linker == LinkerLoad)
	{
		bShouldDetachExisting = false; // no change so don't call notify
	}
	LinkerAnnotation.AddAnnotation(this,FLinkerIndexPair(LinkerLoad,LinkerIndex));
	if (bShouldDetachExisting)
	{
#if WITH_EDITOR
		PostLinkerChange();
#else
		UE_CLOG(Existing.Linker && LinkerLoad, LogUObjectLinker, Fatal,
			TEXT("It is only legal to change linkers in the editor. Trying to change linker on %s from %s (Existing->LinkerRoot=%s) to %s (LinkerLoad->LinkerRoot=%s)"),
			*GetFullName(),
			*Existing.Linker->Filename,
			*GetNameSafe(Existing.Linker->LinkerRoot),
			*LinkerLoad->Filename,
			*GetNameSafe(LinkerLoad->LinkerRoot));
#endif
	}
}
Esempio n. 4
0
void FWebSocket::OnRawWebSocketWritable(WebSocketInternal* wsi)
{
	if (OutgoingBuffer.Num() == 0 || OutgoingBufferType.Num() == 0)
		return;

	CriticalSection.Lock();
	TArray <uint8>& Packet = OutgoingBuffer[0];
	lws_write_protocol OutType = (lws_write_protocol)OutgoingBufferType[0];
	CriticalSection.Unlock();

#if !PLATFORM_HTML5

	uint32 TotalDataSize = Packet.Num() - LWS_PRE;
	uint32 DataToSend = TotalDataSize;
	while (DataToSend)
	{
		int Sent = lws_write(Wsi, Packet.GetData() + LWS_PRE + (DataToSend-TotalDataSize), DataToSend, OutType);
		;
		if (Sent < 0)
		{
			ErrorCallBack.Broadcast();
			return;
		}
		if ((uint32)Sent < DataToSend)
		{
			UE_LOG(LogHTML5Networking, Warning, TEXT("Could not write all '%d' bytes to socket"), DataToSend);
		}
		DataToSend-=Sent;
	}

	check(Wsi == wsi);

#else // PLATFORM_HTML5

	uint32 TotalDataSize = Packet.Num();
	uint32 DataToSend = TotalDataSize;
	while (DataToSend)
	{
		// send actual data in one go.
		int Result = send(SockFd, Packet.GetData()+(DataToSend-TotalDataSize),DataToSend, 0);
		if (Result == -1)
		{
			// we are caught with our pants down. fail.
			UE_LOG(LogHTML5Networking, Error, TEXT("Could not write %d bytes"), Packet.Num());
			ErrorCallBack.Broadcast();
			return;
		}
		UE_CLOG((uint32)Result < DataToSend, LogHTML5Networking, Warning, TEXT("Could not write all '%d' bytes to socket"), DataToSend);
		DataToSend-=Result;
	}

#endif

	// this is very inefficient we need a constant size circular buffer to efficiently not do unnecessary allocations/deallocations.
	CriticalSection.Lock();
	OutgoingBuffer.RemoveAt(0);
	OutgoingBufferType.RemoveAt(0);
	CriticalSection.Unlock();

}
void FUObjectArray::AllocateUObjectIndex(UObjectBase* Object, bool bMergingThreads /*= false*/)
{
	int32 Index = INDEX_NONE;
	check(Object->InternalIndex == INDEX_NONE || bMergingThreads);

	// Special non- garbage collectable range.
	if (OpenForDisregardForGC && DisregardForGCEnabled())
	{
		// Disregard from GC pool is only available from the game thread, at least for now
		check(IsInGameThread());
		Index = ++ObjLastNonGCIndex;
		// Check if we're not out of bounds, unless there hasn't been any gc objects yet
		UE_CLOG(ObjLastNonGCIndex >= MaxObjectsNotConsideredByGC && ObjFirstGCIndex >= 0, LogUObjectArray, Fatal, TEXT("Unable to add more objects to disregard for GC pool (Max: %d)"), MaxObjectsNotConsideredByGC);
		// If we haven't added any GC objects yet, it's fine to keep growing the disregard pool past its initial size.
		if (ObjLastNonGCIndex >= MaxObjectsNotConsideredByGC)
		{
			Index = ObjObjects.AddSingle();
			check(Index == ObjLastNonGCIndex);
		}
		MaxObjectsNotConsideredByGC = FMath::Max(MaxObjectsNotConsideredByGC, ObjLastNonGCIndex + 1);
	}
	// Regular pool/ range.
	else
	{		
		int32* AvailableIndex = ObjAvailableList.Pop();
		if (AvailableIndex)
		{
#if UE_GC_TRACK_OBJ_AVAILABLE
			const int32 AvailableCount = ObjAvailableCount.Decrement();
			checkSlow(AvailableCount >= 0);
#endif
			Index = (int32)(uintptr_t)AvailableIndex;
			check(ObjObjects[Index].Object==nullptr);
		}
		else
		{
			// Make sure ObjFirstGCIndex is valid, otherwise we didn't close the disregard for GC set
			check(ObjFirstGCIndex >= 0);
#if THREADSAFE_UOBJECTS
			FScopeLock ObjObjectsLock(&ObjObjectsCritical);
#else
			check(IsInGameThread());
#endif
			Index = ObjObjects.AddSingle();			
		}
		check(Index >= ObjFirstGCIndex && Index > ObjLastNonGCIndex);
	}
	// Add to global table.
	if (FPlatformAtomics::InterlockedCompareExchangePointer((void**)&ObjObjects[Index].Object, Object, NULL) != NULL) // we use an atomic operation to check for unexpected concurrency, verify alignment, etc
	{
		UE_LOG(LogUObjectArray, Fatal, TEXT("Unexpected concurency while adding new object"));
	}
	IndexToObject(Index)->ResetSerialNumberAndFlags();
	Object->InternalIndex = Index;
	//  @todo: threading: lock UObjectCreateListeners
	for (int32 ListenerIndex = 0; ListenerIndex < UObjectCreateListeners.Num(); ListenerIndex++)
	{
		UObjectCreateListeners[ListenerIndex]->NotifyUObjectCreated(Object,Index);
	}
}
void FLazyObjectPtr::PossiblySerializeObjectGuid(UObject *Object, FArchive& Ar)
{
	if (Ar.IsSaving() || Ar.IsCountingMemory())
	{
		FUniqueObjectGuid Guid = GuidAnnotation.GetAnnotation(Object);
		bool HasGuid = Guid.IsValid();
		Ar << HasGuid;
		if (HasGuid)
		{
			if (Ar.GetPortFlags() & PPF_DuplicateForPIE)
			{
				check(GPlayInEditorID != -1);
				FGuid &FoundGuid = PIEGuidMap[GPlayInEditorID % MAX_PIE_INSTANCES].FindOrAdd(Guid.GetGuid());
				if (!FoundGuid.IsValid())
				{
					Guid = FoundGuid = FGuid::NewGuid();
				}
				else
				{
					Guid = FoundGuid;
				}
			}

			Ar << Guid;
		}
	}
	else if (Ar.IsLoading())
	{
		bool HasGuid = false;
		Ar << HasGuid;
		if (HasGuid)
		{
			FUniqueObjectGuid Guid;
			Ar << Guid;

			// Don't try and resolve GUIDs when loading a package for diff'ing
			const UPackage* Package = Object->GetOutermost();
			const bool bLoadedForDiff = (Package && Package->HasAnyPackageFlags(PKG_ForDiffing));
			if (!bLoadedForDiff && (!(Ar.GetPortFlags() & PPF_Duplicate) || (Ar.GetPortFlags() & PPF_DuplicateForPIE)))
			{
				check(!Guid.IsDefault());
				UObject* OtherObject = Guid.ResolveObject();
				if (OtherObject != Object) // on undo/redo, the object (potentially) already exists
				{
					if (OtherObject != NULL)
					{
						UE_CLOG(!((FApp::IsGame() || GIsPlayInEditorWorld) && Package && Package->ContainsMap()), LogUObjectGlobals, Warning, TEXT("Guid is in use by %s and %s, which should never happen in the editor but could happen at runtime with duplicate level loading or PIE"), *OtherObject->GetFullName(), !!Object ? *Object->GetFullName() : TEXT("NULL"));
						// This guid is in use, which should never happen in the editor but could happen at runtime with duplicate level loading or PIE. If so give it an invalid GUID and don't add to the annotation map.
						Guid = FGuid();
					}
					else
					{
						GuidAnnotation.AddAnnotation(Object, Guid);
					}
					FUniqueObjectGuid::InvalidateTag();
				}
			}
		}
	}
}
Esempio n. 7
0
/**
 * Thread-safe abstract compression routine. Compresses memory from uncompressed buffer and writes it to compressed
 * buffer. Updates CompressedSize with size of compressed data.
 *
 * @param	UncompressedBuffer			Buffer containing uncompressed data
 * @param	UncompressedSize			Size of uncompressed data in bytes
 * @param	CompressedBuffer			Buffer compressed data is going to be read from
 * @param	CompressedSize				Size of CompressedBuffer data in bytes
 * @return true if compression succeeds, false if it fails because CompressedBuffer was too small or other reasons
 */
bool appUncompressMemoryZLIB( void* UncompressedBuffer, int32 UncompressedSize, const void* CompressedBuffer, int32 CompressedSize )
{
    DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "Uncompress Memory ZLIB" ), STAT_appUncompressMemoryZLIB, STATGROUP_Compression );

    // Zlib wants to use unsigned long.
    unsigned long ZCompressedSize	= CompressedSize;
    unsigned long ZUncompressedSize	= UncompressedSize;

    z_stream stream;
    stream.zalloc = &zalloc;
    stream.zfree = &zfree;
    stream.opaque = Z_NULL;
    stream.next_in = (uint8*)CompressedBuffer;
    stream.avail_in = ZCompressedSize;
    stream.next_out = (uint8*)UncompressedBuffer;
    stream.avail_out = ZUncompressedSize;

    int32 Result = inflateInit(&stream);

    if(Result != Z_OK)
        return false;

    // Uncompress data.
    Result = inflate(&stream, Z_FINISH);

    if(Result == Z_STREAM_END)
    {
        ZUncompressedSize = stream.total_out;
    }

    Result = inflateEnd(&stream);

    // These warnings will be compiled out in shipping.
    UE_CLOG(Result == Z_MEM_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_MEM_ERROR, not enough memory!"));
    UE_CLOG(Result == Z_BUF_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_BUF_ERROR, not enough room in the output buffer!"));
    UE_CLOG(Result == Z_DATA_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_DATA_ERROR, input data was corrupted or incomplete!"));

    const bool bOperationSucceeded = (Result == Z_OK);

    // Sanity check to make sure we uncompressed as much data as we expected to.
    check( UncompressedSize == ZUncompressedSize );
    return bOperationSucceeded;
}
Esempio n. 8
0
void FWebSocket::OnRawWebSocketWritable(WebSocketInternal* wsi)
{
	if (OutgoingBuffer.Num() == 0)
		return;

	TArray <uint8>& Packet = OutgoingBuffer[0];

#if !PLATFORM_HTML5_BROWSER

	uint32 TotalDataSize = Packet.Num() - LWS_SEND_BUFFER_PRE_PADDING - LWS_SEND_BUFFER_POST_PADDING;
	uint32 DataToSend = TotalDataSize;
	while (DataToSend)
	{
		int Sent = libwebsocket_write(Wsi, Packet.GetData() + LWS_SEND_BUFFER_PRE_PADDING + (DataToSend-TotalDataSize), DataToSend, (libwebsocket_write_protocol)LWS_WRITE_BINARY);
		if (Sent < 0)
		{
			ErrorCallBack.ExecuteIfBound();
			return;
		}
		if ((uint32)Sent < DataToSend)
		{
			UE_LOG(LogHTML5Networking, Warning, TEXT("Could not write all '%d' bytes to socket"), DataToSend);
		}
		DataToSend-=Sent;
	}

	check(Wsi == wsi);

#endif

#if  PLATFORM_HTML5_BROWSER

	uint32 TotalDataSize = Packet.Num();
	uint32 DataToSend = TotalDataSize;
	while (DataToSend)
	{
		// send actual data in one go. 
		int Result = send(SockFd, Packet.GetData()+(DataToSend-TotalDataSize),DataToSend, 0);
		if (Result == -1)
		{
			// we are caught with our pants down. fail. 
			UE_LOG(LogHTML5Networking, Error, TEXT("Could not write %d bytes"), Packet.Num());
			ErrorCallBack.ExecuteIfBound(); 
			return;
		}
		UE_CLOG((uint32)Result < DataToSend, LogHTML5Networking, Warning, TEXT("Could not write all '%d' bytes to socket"), DataToSend);
		DataToSend-=Result;
	}
	
#endif 

	// this is very inefficient we need a constant size circular buffer to efficiently not do unnecessary allocations/deallocations. 
	OutgoingBuffer.RemoveAt(0);

}
const FString& FSandboxPlatformFile::GetAbsolutePathToGameDirectory()
{
	if (AbsoluteGameDirectory.IsEmpty())
	{
		AbsoluteGameDirectory = FPaths::GetProjectFilePath();
		UE_CLOG(AbsoluteGameDirectory.IsEmpty(), SandboxFile, Fatal, TEXT("SandboxFileWrapper tried to access project path before it was set."));
		AbsoluteGameDirectory = FPaths::ConvertRelativePathToFull(AbsoluteGameDirectory);
		// Strip .uproject filename and game directory, keep just to path to the game directory which could simply be the root dir (but not always).
		AbsoluteGameDirectory = FPaths::GetPath(FPaths::GetPath(AbsoluteGameDirectory));
	}
	return AbsoluteGameDirectory;
}
Esempio n. 10
0
/**
 * Thread-safe abstract compression routine. Compresses memory from uncompressed buffer and writes it to compressed
 * buffer. Updates CompressedSize with size of compressed data.
 *
 * @param	UncompressedBuffer			Buffer containing uncompressed data
 * @param	UncompressedSize			Size of uncompressed data in bytes
 * @param	CompressedBuffer			Buffer compressed data is going to be read from
 * @param	CompressedSize				Size of CompressedBuffer data in bytes
 * @return true if compression succeeds, false if it fails because CompressedBuffer was too small or other reasons
 */
bool appUncompressMemoryZLIB( void* UncompressedBuffer, int32 UncompressedSize, const void* CompressedBuffer, int32 CompressedSize )
{
	DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "Uncompress Memory ZLIB" ), STAT_appUncompressMemoryZLIB, STATGROUP_Compression );

	// Zlib wants to use unsigned long.
	unsigned long ZCompressedSize	= CompressedSize;
	unsigned long ZUncompressedSize	= UncompressedSize;
	
	// Uncompress data.
	const int32 Result = uncompress((uint8*)UncompressedBuffer, &ZUncompressedSize, (const uint8*)CompressedBuffer, ZCompressedSize);
	
	// These warnings will be compiled out in shipping.
	UE_CLOG(Result == Z_MEM_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_MEM_ERROR, not enough memory!"));
	UE_CLOG(Result == Z_BUF_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_BUF_ERROR, not enough room in the output buffer!"));
	UE_CLOG(Result == Z_DATA_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_DATA_ERROR, input data was corrupted or incomplete!"));

	const bool bOperationSucceeded = (Result == Z_OK);

	// Sanity check to make sure we uncompressed as much data as we expected to.
	check( UncompressedSize == ZUncompressedSize );
	return bOperationSucceeded;
}
void UGameplayCueManager::NotifyGameplayCueActorFinished(AGameplayCueNotify_Actor* Actor)
{
	if (GameplayCueActorRecycle)
	{
		if (Actor->bInRecycleQueue)
		{
			// We are already in the recycle queue. This can happen normally
			// (For example the GC is removed and the owner is destroyed in the same frame)
			return;
		}

		AGameplayCueNotify_Actor* CDO = Actor->GetClass()->GetDefaultObject<AGameplayCueNotify_Actor>();
		if (CDO && Actor->Recycle())
		{
			ensure(Actor->IsPendingKill() == false);
			Actor->bInRecycleQueue = true;

			// Remove this now from our internal map so that it doesn't get reused like a currently active cue would
			if (TWeakObjectPtr<AGameplayCueNotify_Actor>* WeakPtrPtr = NotifyMapActor.Find(Actor->NotifyKey))
			{
				WeakPtrPtr->Reset();
			}

			UE_CLOG((GameplayCueActorRecycleDebug>0), LogAbilitySystem, Display, TEXT("NotifyGameplayCueActorFinished %s"), *GetNameSafe(Actor));

			Actor->SetOwner(nullptr);
			Actor->SetActorHiddenInGame(true);
			Actor->DetachRootComponentFromParent();

			FPreallocationInfo& Info = GetPreallocationInfo(Actor->GetWorld());
			TArray<AGameplayCueNotify_Actor*>& PreAllocatedList = Info.PreallocatedInstances.FindOrAdd(Actor->GetClass());

			// Put the actor back in the list
			if (ensureMsgf(PreAllocatedList.Contains(Actor)==false, TEXT("GC Actor PreallocationList already contains Actor %s"), *GetNameSafe(Actor)))
			{
				PreAllocatedList.Push(Actor);
			}
			
#if WITH_EDITOR
			// let things know that we 'de-spawned'
			ISequenceRecorder& SequenceRecorder	= FModuleManager::LoadModuleChecked<ISequenceRecorder>("SequenceRecorder");
			SequenceRecorder.NotifyActorStopRecording(Actor);
#endif
			return;
		}
	}	

	// We didn't recycle, so just destroy
	Actor->Destroy();
}
Esempio n. 12
0
int32 FUObjectArray::AllocateSerialNumber(int32 Index)
{
	FUObjectItem* ObjectItem = IndexToObject(Index);
	checkSlow(ObjectItem);

	volatile int32 *SerialNumberPtr = &ObjectItem->SerialNumber;
	int32 SerialNumber = *SerialNumberPtr;
	if (!SerialNumber)
	{
		SerialNumber = MasterSerialNumber.Increment();
		UE_CLOG(SerialNumber <= START_SERIAL_NUMBER, LogUObjectArray, Fatal, TEXT("UObject serial numbers overflowed (trying to allocate serial number %d)."), SerialNumber);
		int32 ValueWas = FPlatformAtomics::InterlockedCompareExchange((int32*)SerialNumberPtr, SerialNumber, 0);
		if (ValueWas != 0)
		{
			// someone else go it first, use their value
			SerialNumber = ValueWas;
		}
	}
	checkSlow(SerialNumber > START_SERIAL_NUMBER);
	return SerialNumber;
}
void FOculusInput::SetHapticFeedbackValues(int32 ControllerId, int32 Hand, const FHapticFeedbackValues& Values)
{
	for (FOculusTouchControllerPair& ControllerPair : ControllerPairs)
	{
		if (ControllerPair.UnrealControllerIndex == ControllerId)
		{
			FOculusTouchControllerState& ControllerState = ControllerPair.ControllerStates[Hand];
			if (ControllerState.bIsCurrentlyTracked)
			{
				if(IOculusRiftPlugin::IsAvailable())
				{
					FOvrSessionShared::AutoSession OvrSession(IOculusRiftPlugin::Get().GetSession());
					if (OvrSession && FApp::HasVRFocus())
					{
						float FreqMin, FreqMax = 0.f;
						GetHapticFrequencyRange(FreqMin, FreqMax);

						const float Frequency = FMath::Lerp(FreqMin, FreqMax, FMath::Clamp(Values.Frequency, 0.f, 1.f));
						const float Amplitude = Values.Amplitude * GetHapticAmplitudeScale();

						if ((ControllerState.HapticAmplitude != Amplitude) || (ControllerState.HapticFrequency != Frequency))
						{
							ControllerState.HapticAmplitude = Amplitude;
							ControllerState.HapticFrequency = Frequency;

							const ovrControllerType OvrController = (EControllerHand(Hand) == EControllerHand::Left) ? ovrControllerType_LTouch : ovrControllerType_RTouch;
							ovr_SetControllerVibration(OvrSession, OvrController, Frequency, Amplitude);

							UE_CLOG(0, LogOcInput, Log, TEXT("SetHapticFeedbackValues: Hand %d, freq %f, amp %f"), int(Hand), Frequency, Amplitude);

							ControllerState.bPlayingHapticEffect = (Amplitude != 0.f) && (Frequency != 0.f);
						}
					}
				}
			}

			break;
		}
	}
}
FArchive& operator<<( FArchive& Ar, FPackageFileSummary& Sum )
{
	bool bCanStartSerializing = true;
	int64 ArchiveSize = 0;
	if (Ar.IsLoading())
	{
		// Sanity checks before we even start serializing the archive
		ArchiveSize = Ar.TotalSize();
		const int64 MinimumPackageSize = 32; // That should get us safely to Sum.TotalHeaderSize
		bCanStartSerializing = ArchiveSize >= MinimumPackageSize;
		UE_CLOG(!bCanStartSerializing, LogLinker, Warning,
			TEXT("Failed to read package file summary, the file \"%s\" is too small (%lld bytes, expected at least %lld bytes)"),
			*Ar.GetArchiveName(), ArchiveSize, MinimumPackageSize);
	}
	if (bCanStartSerializing)
	{
		Ar << Sum.Tag;
	}
	// only keep loading if we match the magic
	if( Sum.Tag == PACKAGE_FILE_TAG || Sum.Tag == PACKAGE_FILE_TAG_SWAPPED )
	{
		// The package has been stored in a separate endianness than the linker expected so we need to force
		// endian conversion. Latent handling allows the PC version to retrieve information about cooked packages.
		if( Sum.Tag == PACKAGE_FILE_TAG_SWAPPED )
		{
			// Set proper tag.
			Sum.Tag = PACKAGE_FILE_TAG;
			// Toggle forced byte swapping.
			if( Ar.ForceByteSwapping() )
			{
				Ar.SetByteSwapping( false );
			}
			else
			{
				Ar.SetByteSwapping( true );
			}
		}
		/**
		 * The package file version number when this package was saved.
		 *
		 * Lower 16 bits stores the UE3 engine version
		 * Upper 16 bits stores the UE4/licensee version
		 * For newer packages this is -5
		 *		-2 indicates presence of enum-based custom versions
		 *		-3 indicates guid-based custom versions
		 *		-4 indicates removal of the UE3 version. Packages saved with this ID cannot be loaded in older engine versions 
		 *      -5 indicates the replacement of writing out the "UE3 version" so older versions of engine can gracefully fail to open newer packages
		 */
		int32 LegacyFileVersion = -5;
		Ar << LegacyFileVersion;

		if (Ar.IsLoading())
		{
			if (LegacyFileVersion < 0) // means we have modern version numbers
			{
				if (LegacyFileVersion != -4)
				{
					int32 LegacyUE3Version = 0;
					Ar << LegacyUE3Version;
				}
				Ar << Sum.FileVersionUE4;
				Ar << Sum.FileVersionLicenseeUE4;

				if (LegacyFileVersion <= -2)
				{
					Sum.CustomVersionContainer.Serialize(Ar, (LegacyFileVersion == -2) ? ECustomVersionSerializationFormat::Enums : ECustomVersionSerializationFormat::Guids);
				}

				if (!Sum.FileVersionUE4 && !Sum.FileVersionLicenseeUE4)
				{
					// this file is unversioned, remember that, then use current versions
					Sum.bUnversioned = true;
					Sum.FileVersionUE4 = GPackageFileUE4Version;
					Sum.FileVersionLicenseeUE4 = GPackageFileLicenseeUE4Version;

					Sum.CustomVersionContainer = FCustomVersionContainer::GetRegistered();
				}
			}
			else
			{
				// This is probably an old UE3 file, make sure that the linker will fail to load with it.
				Sum.FileVersionUE4 = 0;
				Sum.FileVersionLicenseeUE4 = 0;
			}
		}
		else
		{
			if (Sum.bUnversioned)
			{
				int32 Zero = 0;
				Ar << Zero; // LegacyUE3version
				Ar << Zero; // VersionUE4
				Ar << Zero; // VersionLicenseeUE4

				FCustomVersionContainer NoCustomVersions;
				NoCustomVersions.Serialize(Ar);
			}
			else
			{
				// Must write out the last UE3 engine version, so that older versions identify it as new
				int32 LegacyUE3Version = 864;
				Ar << LegacyUE3Version;
				Ar << Sum.FileVersionUE4;
				Ar << Sum.FileVersionLicenseeUE4;

				// Serialise custom version map.
				Sum.CustomVersionContainer.Serialize(Ar);
			}
		}
		Ar << Sum.TotalHeaderSize;
		Ar << Sum.FolderName;
		Ar << Sum.PackageFlags;

#if WITH_EDITOR
		if (Ar.IsLoading())
		{
			// This flag should never be saved and its reused, so we need to make sure it hasn't been loaded.
			Sum.PackageFlags &= ~PKG_NewlyCreated;
		}
#endif // WITH_EDITOR

		if( Sum.PackageFlags & PKG_FilterEditorOnly )
		{
			Ar.SetFilterEditorOnly(true);
		}
		Ar << Sum.NameCount					<< Sum.NameOffset;
		if (Sum.FileVersionUE4 >= VER_UE4_SERIALIZE_TEXT_IN_PACKAGES)
		{
			Ar << Sum.GatherableTextDataCount	<< Sum.GatherableTextDataOffset;
		}
		Ar << Sum.ExportCount				<< Sum.ExportOffset;
		Ar << Sum.ImportCount				<< Sum.ImportOffset;
		Ar << Sum.DependsOffset;

		if (Ar.IsLoading() && (Sum.FileVersionUE4 < VER_UE4_OLDEST_LOADABLE_PACKAGE || Sum.FileVersionUE4 > GPackageFileUE4Version))
		{
			return Ar; // we can't safely load more than this because the below was different in older files.
		}

		if (Ar.IsSaving() || Sum.FileVersionUE4 >= VER_UE4_ADD_STRING_ASSET_REFERENCES_MAP)
		{
			Ar << Sum.StringAssetReferencesCount << Sum.StringAssetReferencesOffset;
		}

		Ar << Sum.ThumbnailTableOffset;

		int32 GenerationCount = Sum.Generations.Num();
		Ar << Sum.Guid << GenerationCount;
		if( Ar.IsLoading() && GenerationCount > 0 )
		{
			Sum.Generations.Empty( 1 );
			Sum.Generations.AddUninitialized( GenerationCount );
		}
		for( int32 i=0; i<GenerationCount; i++ )
		{
			Sum.Generations[i].Serialize(Ar, Sum);
		}

		if( Sum.GetFileVersionUE4() >= VER_UE4_ENGINE_VERSION_OBJECT )
		{
			if(Ar.IsCooking() || (Ar.IsSaving() && !GEngineVersion.HasChangelist()))
			{
				FEngineVersion EmptyEngineVersion;
				Ar << EmptyEngineVersion;
			}
			else
			{
				Ar << Sum.SavedByEngineVersion;
			}
		}
		else
		{
			int32 EngineChangelist = 0;
			Ar << EngineChangelist;

			if(Ar.IsLoading() && EngineChangelist != 0)
			{
				Sum.SavedByEngineVersion.Set(4, 0, 0, EngineChangelist, TEXT(""));
			}
		}

		if (Sum.GetFileVersionUE4() >= VER_UE4_PACKAGE_SUMMARY_HAS_COMPATIBLE_ENGINE_VERSION )
		{
			if(Ar.IsCooking() || (Ar.IsSaving() && !GEngineVersion.HasChangelist()))
			{
				FEngineVersion EmptyEngineVersion;
				Ar << EmptyEngineVersion;
			}
			else
			{
				Ar << Sum.CompatibleWithEngineVersion;
			}
		}
		else
		{
			if (Ar.IsLoading())
			{
				Sum.CompatibleWithEngineVersion = Sum.SavedByEngineVersion;
			}
		}

		Ar << Sum.CompressionFlags;
		Ar << Sum.CompressedChunks;
		Ar << Sum.PackageSource;

		Ar << Sum.AdditionalPackagesToCook;

#if WITH_ENGINE
		//@todo legacy
		Ar << Sum.TextureAllocations;
#else
		check(!"this can't serialize successfully");
#endif		// WITH_ENGINE

		Ar << Sum.AssetRegistryDataOffset;
		Ar << Sum.BulkDataStartOffset;
		
		if (Sum.GetFileVersionUE4() >= VER_UE4_WORLD_LEVEL_INFO)
		{
			Ar << Sum.WorldTileInfoDataOffset;
		}

		if (Sum.GetFileVersionUE4() >= VER_UE4_CHANGED_CHUNKID_TO_BE_AN_ARRAY_OF_CHUNKIDS)
		{
			Ar << Sum.ChunkIDs;
		}
		else if (Sum.GetFileVersionUE4() >= VER_UE4_ADDED_CHUNKID_TO_ASSETDATA_AND_UPACKAGE)
		{
			// handle conversion of single ChunkID to an array of ChunkIDs
			if (Ar.IsLoading())
			{
				int ChunkID = -1;
				Ar << ChunkID;

				// don't load <0 entries since an empty array represents the same thing now
				if (ChunkID >= 0)
				{
					Sum.ChunkIDs.Add( ChunkID );
				}
			}
		}
	}

	return Ar;
}
AGameplayCueNotify_Actor* UGameplayCueManager::GetInstancedCueActor(AActor* TargetActor, UClass* CueClass, const FGameplayCueParameters& Parameters)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_GameplayCueManager_GetInstancedCueActor);


	// First, see if this actor already have a GameplayCueNotifyActor already going for this CueClass
	AGameplayCueNotify_Actor* CDO = Cast<AGameplayCueNotify_Actor>(CueClass->ClassDefaultObject);
	FGCNotifyActorKey	NotifyKey(TargetActor, CueClass, 
							CDO->bUniqueInstancePerInstigator ? Parameters.GetInstigator() : nullptr, 
							CDO->bUniqueInstancePerSourceObject ? Parameters.GetSourceObject() : nullptr);

	AGameplayCueNotify_Actor* SpawnedCue = nullptr;
	if (TWeakObjectPtr<AGameplayCueNotify_Actor>* WeakPtrPtr = NotifyMapActor.Find(NotifyKey))
	{		
		SpawnedCue = WeakPtrPtr->Get();
		// If the cue is scheduled to be destroyed, don't reuse it, create a new one instead
		if (SpawnedCue && SpawnedCue->GameplayCuePendingRemove() == false)
		{
			if (SpawnedCue->GetOwner() != TargetActor)
			{
				// This should not happen. This means we think we can recycle and GC actor that is currently being used by someone else.
				ABILITY_LOG(Warning, TEXT("GetInstancedCueActor attempting to reuse GC Actor with a different owner! %s (Target: %s). Using GC Actor: %s. Current Owner: %s"), *GetNameSafe(CueClass), *GetNameSafe(TargetActor), *GetNameSafe(SpawnedCue), *GetNameSafe(SpawnedCue->GetOwner()));
			}
			else
			{
				UE_CLOG((GameplayCueActorRecycleDebug>0), LogAbilitySystem, Display, TEXT("::GetInstancedCueActor Using Existing %s (Target: %s). Using GC Actor: %s"), *GetNameSafe(CueClass), *GetNameSafe(TargetActor), *GetNameSafe(SpawnedCue));
				return SpawnedCue;
			}
		}
	}

	// We don't have an instance for this, and we need one, so make one
	if (ensure(TargetActor) && ensure(CueClass))
	{
		AActor* NewOwnerActor = TargetActor;
#if WITH_EDITOR
		// Don't set owner if we are using fake CDO actor to do anim previewing
		NewOwnerActor= (TargetActor && TargetActor->HasAnyFlags(RF_ClassDefaultObject) == false ? TargetActor : nullptr);
#endif

		// Look to reuse an existing one that is stored on the CDO:
		if (GameplayCueActorRecycle > 0)
		{
			FPreallocationInfo& Info = GetPreallocationInfo(GetWorld());
			TArray<AGameplayCueNotify_Actor*>* PreallocatedList = Info.PreallocatedInstances.Find(CueClass);
			if (PreallocatedList && PreallocatedList->Num() > 0)
			{
				SpawnedCue = PreallocatedList->Pop(false);
				checkf(SpawnedCue && SpawnedCue->IsPendingKill() == false, TEXT("Spawned Cue is pending kill or null: %s"), *GetNameSafe(SpawnedCue));
				SpawnedCue->bInRecycleQueue = false;				
				SpawnedCue->SetActorHiddenInGame(false);
				SpawnedCue->SetOwner(NewOwnerActor);
				SpawnedCue->SetActorLocationAndRotation(TargetActor->GetActorLocation(), TargetActor->GetActorRotation());

				UE_CLOG((GameplayCueActorRecycleDebug>0), LogAbilitySystem, Display, TEXT("GetInstancedCueActor Popping Recycled %s (Target: %s). Using GC Actor: %s"), *GetNameSafe(CueClass), *GetNameSafe(TargetActor), *GetNameSafe(SpawnedCue));
#if WITH_EDITOR
				// let things know that we 'spawned'
				ISequenceRecorder& SequenceRecorder	= FModuleManager::LoadModuleChecked<ISequenceRecorder>("SequenceRecorder");
				SequenceRecorder.NotifyActorStartRecording(SpawnedCue);
#endif
			}
		}

		// If we can't reuse, then spawn a new one
		if (SpawnedCue == nullptr)
		{
			FActorSpawnParameters SpawnParams;
			SpawnParams.Owner = NewOwnerActor;
			if (SpawnedCue == nullptr)
			{
				if (LogGameplayCueActorSpawning)
				{
					ABILITY_LOG(Warning, TEXT("Spawning GameplaycueActor: %s"), *CueClass->GetName());
				}

				SpawnedCue = GetWorld()->SpawnActor<AGameplayCueNotify_Actor>(CueClass, TargetActor->GetActorLocation(), TargetActor->GetActorRotation(), SpawnParams);
			}
		}

		// Associate this GameplayCueNotifyActor with this target actor/key
		if (ensure(SpawnedCue))
		{
			SpawnedCue->NotifyKey = NotifyKey;
			NotifyMapActor.Add(NotifyKey, SpawnedCue);
		}
	}

	UE_CLOG((GameplayCueActorRecycleDebug>0), LogAbilitySystem, Display, TEXT("GetInstancedCueActor  Returning %s (Target: %s). Using GC Actor: %s"), *GetNameSafe(CueClass), *GetNameSafe(TargetActor), *GetNameSafe(SpawnedCue));
	return SpawnedCue;
}
void FRedirectCollector::ResolveStringAssetReference(FString FilterPackage)
{
	TMultiMap<FString, FPackagePropertyPair> SkippedReferences;
	while (StringAssetReferences.Num())
	{
		TMultiMap<FString, FPackagePropertyPair>::TIterator First(StringAssetReferences);
		FString ToLoad = First.Key();
		FPackagePropertyPair RefFilenameAndProperty = First.Value();
		First.RemoveCurrent();
		
		if (FCoreDelegates::LoadStringAssetReferenceInCook.IsBound())
		{
			if (FCoreDelegates::LoadStringAssetReferenceInCook.Execute(ToLoad) == false)
			{
				// Skip this reference
				continue;
			}
		}

		if (!FilterPackage.IsEmpty() && FilterPackage != RefFilenameAndProperty.Package)
		{
			// If we have a valid filter and it doesn't match, skip this reference
			SkippedReferences.Add(ToLoad, RefFilenameAndProperty);
			continue;
		}

		if (ToLoad.Len() > 0)
		{
			UE_LOG(LogRedirectors, Verbose, TEXT("String Asset Reference '%s'"), *ToLoad);
			UE_CLOG(RefFilenameAndProperty.Property.Len(), LogRedirectors, Verbose, TEXT("    Referenced by '%s'"), *RefFilenameAndProperty.Property);

			StringAssetRefFilenameStack.Push(RefFilenameAndProperty.Package);

			UObject *Loaded = LoadObject<UObject>(NULL, *ToLoad, NULL, RefFilenameAndProperty.bReferencedByEditorOnlyProperty ? LOAD_EditorOnly : LOAD_None, NULL);
			StringAssetRefFilenameStack.Pop();

			UObjectRedirector* Redirector = dynamic_cast<UObjectRedirector*>(Loaded);
			if (Redirector)
			{
				UE_LOG(LogRedirectors, Verbose, TEXT("    Found redir '%s'"), *Redirector->GetFullName());
				FRedirection Redir;
				Redir.PackageFilename = RefFilenameAndProperty.Package;
				Redir.RedirectorName = Redirector->GetFullName();
				Redir.RedirectorPackageFilename = Redirector->GetLinker()->Filename;
				CA_SUPPRESS(28182)
				Redir.DestinationObjectName = Redirector->DestinationObject->GetFullName();
				Redirections.AddUnique(Redir);
				Loaded = Redirector->DestinationObject;
			}
			if (Loaded)
			{
				FString Dest = Loaded->GetPathName();
				UE_LOG(LogRedirectors, Verbose, TEXT("    Resolved to '%s'"), *Dest);
				if (Dest != ToLoad)
				{
					StringAssetRemap.Add(ToLoad, Dest);
				}
			}
			else
			{
				const FString Referencer = RefFilenameAndProperty.Property.Len() ? RefFilenameAndProperty.Property : TEXT("Unknown");
				UE_LOG(LogRedirectors, Warning, TEXT("String Asset Reference '%s' was not found! (Referencer '%s')"), *ToLoad, *Referencer);
			}
		}
	}

	// Add any skipped references back into the map for the next time this is called
	StringAssetReferences = SkippedReferences;
}
Esempio n. 17
0
bool ICrashDebugHelper::Init()
{
	bInitialized = true;

	// Check if we have a valid EngineVersion, if so use it.
	FString CmdEngineVersion;
	const bool bHasEngineVersion = FParse::Value( FCommandLine::Get(), TEXT( "EngineVersion=" ), CmdEngineVersion );
	if( bHasEngineVersion )
	{
		FEngineVersion EngineVersion;
		FEngineVersion::Parse( CmdEngineVersion, EngineVersion );

		// Clean branch name.
		CrashInfo.DepotName = EngineVersion.GetBranch();
		CrashInfo.BuiltFromCL = (int32)EngineVersion.GetChangelist();

		CrashInfo.EngineVersion = CmdEngineVersion;
	}
	else
	{
		// Look up the depot name
		// Try to use the command line param
		FString DepotName;
		FString CmdLineBranchName;
		if( FParse::Value( FCommandLine::Get(), TEXT( "BranchName=" ), CmdLineBranchName ) )
		{
			DepotName = FString::Printf( TEXT( "%s%s" ), P4_DEPOT_PREFIX, *CmdLineBranchName );
		}
		// Default to BRANCH_NAME
		else
		{
			DepotName = FString::Printf( TEXT( "%s" ), TEXT( BRANCH_NAME ) );
		}

		CrashInfo.DepotName = DepotName.Replace( TEXT( "+" ), TEXT( "/" ) );

		// Try to get the BuiltFromCL from command line to use this instead of attempting to locate the CL in the minidump
		FString CmdLineBuiltFromCL;
		int32 BuiltFromCL = -1;
		if( FParse::Value( FCommandLine::Get(), TEXT( "BuiltFromCL=" ), CmdLineBuiltFromCL ) )
		{
			if( !CmdLineBuiltFromCL.IsEmpty() )
			{
				BuiltFromCL = FCString::Atoi( *CmdLineBuiltFromCL );
			}
		}
		// Default to BUILT_FROM_CHANGELIST.
		else
		{
			BuiltFromCL = int32( BUILT_FROM_CHANGELIST );
		}

		CrashInfo.BuiltFromCL = BuiltFromCL;
	}


	UE_LOG( LogCrashDebugHelper, Log, TEXT( "DepotName: %s" ), *CrashInfo.DepotName );
	UE_LOG( LogCrashDebugHelper, Log, TEXT( "BuiltFromCL: %i" ), CrashInfo.BuiltFromCL );
	UE_LOG( LogCrashDebugHelper, Log, TEXT( "EngineVersion: %s" ), *CrashInfo.EngineVersion );
	
	GConfig->GetString( TEXT( "Engine.CrashDebugHelper" ), TEXT( "SourceControlBuildLabelPattern" ), SourceControlBuildLabelPattern, GEngineIni );

	GConfig->GetArray( TEXT( "Engine.CrashDebugHelper" ), TEXT( "ExecutablePathPattern" ), ExecutablePathPatterns, GEngineIni );
	GConfig->GetArray( TEXT( "Engine.CrashDebugHelper" ), TEXT( "SymbolPathPattern" ), SymbolPathPatterns, GEngineIni );
	GConfig->GetArray( TEXT( "Engine.CrashDebugHelper" ), TEXT( "Branch" ), Branches, GEngineIni );
	const bool bCanUseSearchPatterns = Branches.Num() == ExecutablePathPatterns.Num() && ExecutablePathPatterns.Num() == SymbolPathPatterns.Num() && Branches.Num() > 0;
	UE_CLOG( !bCanUseSearchPatterns, LogCrashDebugHelper, Warning, TEXT( "Search patterns don't match" ) );

	if (bCanUseSearchPatterns)
	{
		FPDBCache::Get().Init();
	}
	else
	{
		UE_LOG( LogCrashDebugHelper, Warning, TEXT( "PDB Cache disabled" ) );
	}
	

	return bInitialized;
}
Esempio n. 18
0
TSharedPtr<FEnvQueryInstance> UEnvQueryManager::CreateQueryInstance(const UEnvQuery* Template, EEnvQueryRunMode::Type RunMode)
{
	if (Template == nullptr || Template->Options.Num() == 0)
	{
		UE_CLOG(Template != nullptr && Template->Options.Num() == 0, LogEQS, Warning, TEXT("Query [%s] doesn't have any valid options!"), *Template->GetName());
		return nullptr;
	}

	// try to find entry in cache
	FEnvQueryInstance* InstanceTemplate = NULL;
	for (int32 InstanceIndex = 0; InstanceIndex < InstanceCache.Num(); InstanceIndex++)
	{
		if (InstanceCache[InstanceIndex].Template->GetFName() == Template->GetFName() &&
			InstanceCache[InstanceIndex].Instance.Mode == RunMode)
		{
			InstanceTemplate = &InstanceCache[InstanceIndex].Instance;
			break;
		}
	}

	// and create one if can't be found
	if (InstanceTemplate == NULL)
	{
		SCOPE_CYCLE_COUNTER(STAT_AI_EQS_LoadTime);
		
		// duplicate template in manager's world for BP based nodes
		UEnvQuery* LocalTemplate = (UEnvQuery*)StaticDuplicateObject(Template, this, *Template->GetName());

		{
			// memory stat tracking: temporary variable will exist only inside this section
			FEnvQueryInstanceCache NewCacheEntry;
			NewCacheEntry.Template = LocalTemplate;
			NewCacheEntry.Instance.QueryName = LocalTemplate->GetName();
			NewCacheEntry.Instance.Mode = RunMode;

			const int32 Idx = InstanceCache.Add(NewCacheEntry);
			InstanceTemplate = &InstanceCache[Idx].Instance;
		}

		// NOTE: We must iterate over this from 0->Num because we are copying the options from the template into the
		// instance, and order matters!  Since we also may need to remove invalid or null options, we must decrement
		// the iteration pointer when doing so to avoid problems.
		for (int32 OptionIndex = 0; OptionIndex < LocalTemplate->Options.Num(); ++OptionIndex)
		{
			UEnvQueryOption* MyOption = LocalTemplate->Options[OptionIndex];
			if (MyOption == nullptr ||
				MyOption->Generator == nullptr ||
				MyOption->Generator->ItemType == nullptr)
			{
				UE_LOG(LogEQS, Error, TEXT("Trying to spawn a query with broken Template (generator:%s itemType:%s): %s, option %d"),
					MyOption ? (MyOption->Generator ? TEXT("ok") : TEXT("MISSING")) : TEXT("N/A"),
					(MyOption && MyOption->Generator) ? (MyOption->Generator->ItemType ? TEXT("ok") : TEXT("MISSING")) : TEXT("N/A"),
					*GetNameSafe(LocalTemplate), OptionIndex);

				LocalTemplate->Options.RemoveAt(OptionIndex, 1, false);
				--OptionIndex; // See note at top of for loop.  We cannot iterate backwards here.
				continue;
			}

			UEnvQueryOption* LocalOption = (UEnvQueryOption*)StaticDuplicateObject(MyOption, this, TEXT("None"));
			UEnvQueryGenerator* LocalGenerator = (UEnvQueryGenerator*)StaticDuplicateObject(MyOption->Generator, this, TEXT("None"));
			LocalTemplate->Options[OptionIndex] = LocalOption;
			LocalOption->Generator = LocalGenerator;

			EEnvTestCost::Type HighestCost(EEnvTestCost::Low);
			TArray<UEnvQueryTest*> SortedTests = MyOption->Tests;
			TSubclassOf<UEnvQueryItemType> GeneratedType = MyOption->Generator->ItemType;
			for (int32 TestIndex = SortedTests.Num() - 1; TestIndex >= 0; TestIndex--)
			{
				UEnvQueryTest* TestOb = SortedTests[TestIndex];
				if (TestOb == NULL || !TestOb->IsSupportedItem(GeneratedType))
				{
					UE_LOG(LogEQS, Warning, TEXT("Query [%s] can't use test [%s] in option %d [%s], removing it"),
						*GetNameSafe(LocalTemplate), *GetNameSafe(TestOb), OptionIndex, *MyOption->Generator->OptionName);

					SortedTests.RemoveAt(TestIndex, 1, false);
				}
				else if (HighestCost < TestOb->Cost)
				{
					HighestCost = TestOb->Cost;
				}
			}

			if (SortedTests.Num() == 0)
			{
				UE_LOG(LogEQS, Warning, TEXT("Query [%s] doesn't have any tests in option %d [%s]"),
					*GetNameSafe(LocalTemplate), OptionIndex, *MyOption->Generator->OptionName);

				LocalTemplate->Options.RemoveAt(OptionIndex, 1, false);
				--OptionIndex; // See note at top of for loop.  We cannot iterate backwards here.
				continue;
			}

			LocalOption->Tests.Reset(SortedTests.Num());
			for (int32 TestIdx = 0; TestIdx < SortedTests.Num(); TestIdx++)
			{
				UEnvQueryTest* LocalTest = (UEnvQueryTest*)StaticDuplicateObject(SortedTests[TestIdx], this, TEXT("None"));
				LocalOption->Tests.Add(LocalTest);
			}

			// use locally referenced duplicates
			SortedTests = LocalOption->Tests;

			if (SortedTests.Num() && LocalGenerator->bAutoSortTests)
			{
				switch (RunMode)
				{
				case EEnvQueryRunMode::SingleResult:
					SortedTests.Sort(EnvQueryTestSort::FSingleResult(HighestCost));
					break;

				case EEnvQueryRunMode::RandomBest5Pct:
				case EEnvQueryRunMode::RandomBest25Pct:
				case EEnvQueryRunMode::AllMatching:
					SortedTests.Sort(EnvQueryTestSort::FAllMatching());
					break;

				default:
					{
						UEnum* RunModeEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EEnvQueryRunMode"));
						UE_LOG(LogEQS, Warning, TEXT("Query [%s] can't be sorted for RunMode: %d [%s]"),
							*GetNameSafe(LocalTemplate), (int32)RunMode, RunModeEnum ? *RunModeEnum->GetEnumName(RunMode) : TEXT("??"));
					}
				}
			}

			CreateOptionInstance(LocalOption, SortedTests, *InstanceTemplate);
		}
	}

	if (InstanceTemplate->Options.Num() == 0)
	{
		return nullptr;
	}

	// create new instance
	TSharedPtr<FEnvQueryInstance> NewInstance(new FEnvQueryInstance(*InstanceTemplate));
	return NewInstance;
}
void FRawProfilerSession::PrepareLoading()
{
	SCOPE_LOG_TIME_FUNC();

	const FString Filepath = DataFilepath + FStatConstants::StatsFileRawExtension;
	const int64 Size = IFileManager::Get().FileSize( *Filepath );
	if( Size < 4 )
	{
		UE_LOG( LogStats, Error, TEXT( "Could not open: %s" ), *Filepath );
		return;
	}
	TAutoPtr<FArchive> FileReader( IFileManager::Get().CreateFileReader( *Filepath ) );
	if( !FileReader )
	{
		UE_LOG( LogStats, Error, TEXT( "Could not open: %s" ), *Filepath );
		return;
	}

	if( !Stream.ReadHeader( *FileReader ) )
	{
		UE_LOG( LogStats, Error, TEXT( "Could not open, bad magic: %s" ), *Filepath );
		return;
	}

	const bool bIsFinalized = Stream.Header.IsFinalized();
	check( bIsFinalized );
	check( Stream.Header.Version == EStatMagicWithHeader::VERSION_5 );
	StatsThreadStats.MarkAsLoaded();

	TArray<FStatMessage> Messages;
	if( Stream.Header.bRawStatsFile )
	{
		// Read metadata.
		TArray<FStatMessage> MetadataMessages;
		Stream.ReadFNamesAndMetadataMessages( *FileReader, MetadataMessages );
		StatsThreadStats.ProcessMetaDataOnly( MetadataMessages );

		const FName F00245 = FName(245, 245, 0);
		
		const FName F11602 = FName(11602, 11602, 0);
		const FName F06394 = FName(6394, 6394, 0);

		const int64 CurrentFilePos = FileReader->Tell();

		// Update profiler's metadata.
		StatMetaData->UpdateFromStatsState( StatsThreadStats );
		const uint32 GameThreadID = GetMetaData()->GetGameThreadID();

		// Read frames offsets.
		Stream.ReadFramesOffsets( *FileReader );

		// Buffer used to store the compressed and decompressed data.
		TArray<uint8> SrcArray;
		TArray<uint8> DestArray;
		const bool bHasCompressedData = Stream.Header.HasCompressedData();
		check(bHasCompressedData);

		TMap<int64, FStatPacketArray> CombinedHistory;
		int64 TotalPacketSize = 0;
		int64 MaximumPacketSize = 0;
		// Read all packets sequentially, force by the memory profiler which is now a part of the raw stats.
		// !!CAUTION!! Frame number in the raw stats is pointless, because it is time based, not frame based.
		// Background threads usually execute time consuming operations, so the frame number won't be valid.
		// Needs to be combined by the thread and the time, not by the frame number.
		{
			int64 FrameOffset0 = Stream.FramesInfo[0].FrameFileOffset;
			FileReader->Seek( FrameOffset0 );

			const int64 FileSize = FileReader->TotalSize();

			while( FileReader->Tell() < FileSize )
			{
				// Read the compressed data.
				FCompressedStatsData UncompressedData( SrcArray, DestArray );
				*FileReader << UncompressedData;
				if( UncompressedData.HasReachedEndOfCompressedData() )
				{
					break;
				}

				FMemoryReader MemoryReader( DestArray, true );

				FStatPacket* StatPacket = new FStatPacket();
				Stream.ReadStatPacket( MemoryReader, *StatPacket );
				
				const int64 FrameNum = StatPacket->Frame;
				FStatPacketArray& Frame = CombinedHistory.FindOrAdd(FrameNum);
			
				// Check if we need to combine packets from the same thread.
				FStatPacket** CombinedPacket = Frame.Packets.FindByPredicate([&](FStatPacket* Item) -> bool
				{
					return Item->ThreadId == StatPacket->ThreadId;
				});
				
				if( CombinedPacket )
				{
					(*CombinedPacket)->StatMessages += StatPacket->StatMessages;
				}
				else
				{
					Frame.Packets.Add(StatPacket);
				}

				const int64 CurrentPos = FileReader->Tell();
				const int32 PctPos = int32(100.0f*CurrentPos/FileSize);

				UE_LOG( LogStats, Log, TEXT( "%3i Processing FStatPacket: Frame %5i for thread %5i with %6i messages (%.1f MB)" ), 
					PctPos, 
					StatPacket->Frame, 
					StatPacket->ThreadId, 
					StatPacket->StatMessages.Num(), 
					StatPacket->StatMessages.GetAllocatedSize()/1024.0f/1024.0f );

				const int64 PacketSize = StatPacket->StatMessages.GetAllocatedSize();
				TotalPacketSize += PacketSize;
				MaximumPacketSize = FMath::Max( MaximumPacketSize, PacketSize );
			}
		}

		UE_LOG( LogStats, Log, TEXT( "TotalPacketSize: %.1f MB, Max: %1f MB" ), 
			TotalPacketSize/1024.0f/1024.0f, 
			MaximumPacketSize/1024.0f/1024.0f );

		TArray<int64> Frames;
		CombinedHistory.GenerateKeyArray(Frames);
		Frames.Sort();
		const int64 MiddleFrame = Frames[Frames.Num()/2];


		// Remove all frames without the game thread messages.
		for (int32 FrameIndex = 0; FrameIndex < Frames.Num(); ++FrameIndex)
		{
			const int64 TargetFrame = Frames[FrameIndex];
			const FStatPacketArray& Frame = CombinedHistory.FindChecked( TargetFrame );

			const double GameThreadTimeMS = GetMetaData()->ConvertCyclesToMS( GetFastThreadFrameTimeInternal( Frame, EThreadType::Game ) );

			if (GameThreadTimeMS == 0.0f)
			{
				CombinedHistory.Remove( TargetFrame );
				Frames.RemoveAt( FrameIndex );
				FrameIndex--;
			}
		}
		
	
		StatMetaData->SecondsPerCycle = GetSecondsPerCycle( CombinedHistory.FindChecked(MiddleFrame) );
		check( StatMetaData->GetSecondsPerCycle() > 0.0 );

		//const int32 FirstGameThreadFrame = FindFirstFrameWithGameThread( CombinedHistory, Frames );

		// Prepare profiler frame.
		{
			SCOPE_LOG_TIME( TEXT( "Preparing profiler frames" ), nullptr );

			// Prepare profiler frames.
			double ElapsedTimeMS = 0;

			for( int32 FrameIndex = 0; FrameIndex < Frames.Num(); ++FrameIndex )
			{
				const int64 TargetFrame = Frames[FrameIndex];
				const FStatPacketArray& Frame = CombinedHistory.FindChecked(TargetFrame);

				const double GameThreadTimeMS = GetMetaData()->ConvertCyclesToMS( GetFastThreadFrameTimeInternal(Frame,EThreadType::Game) );

				if( GameThreadTimeMS == 0.0f )
				{
					continue;
				}

				const double RenderThreadTimeMS = GetMetaData()->ConvertCyclesToMS( GetFastThreadFrameTimeInternal(Frame,EThreadType::Renderer) );

				// Update mini-view, convert from cycles to ms.
				TMap<uint32, float> ThreadTimesMS;
				ThreadTimesMS.Add( GameThreadID, GameThreadTimeMS );
				ThreadTimesMS.Add( GetMetaData()->GetRenderThreadID()[0], RenderThreadTimeMS );

				// Pass the reference to the stats' metadata.
				OnAddThreadTime.ExecuteIfBound( FrameIndex, ThreadTimesMS, StatMetaData );

				// Create a new profiler frame and add it to the stream.
				ElapsedTimeMS += GameThreadTimeMS;
				FProfilerFrame* ProfilerFrame = new FProfilerFrame( TargetFrame, GameThreadTimeMS, ElapsedTimeMS );
				ProfilerFrame->ThreadTimesMS = ThreadTimesMS;
				ProfilerStream.AddProfilerFrame( TargetFrame, ProfilerFrame );
			}
		}
	
		// Process the raw stats data.
		{
			SCOPE_LOG_TIME( TEXT( "Processing the raw stats" ), nullptr );

			double CycleCounterAdjustmentMS = 0.0f;

			// Read the raw stats messages.
			for( int32 FrameIndex = 0; FrameIndex < Frames.Num()-1; ++FrameIndex )
			{
				const int64 TargetFrame = Frames[FrameIndex];
				const FStatPacketArray& Frame = CombinedHistory.FindChecked(TargetFrame);

				FProfilerFrame* ProfilerFrame = ProfilerStream.GetProfilerFrame( FrameIndex );

				UE_CLOG( FrameIndex % 8 == 0, LogStats, Log, TEXT( "Processing raw stats frame: %4i/%4i" ), FrameIndex, Frames.Num() );

				ProcessStatPacketArray( Frame, *ProfilerFrame, FrameIndex ); // or ProfilerFrame->TargetFrame

				// Find the first cycle counter for the game thread.
				if( CycleCounterAdjustmentMS == 0.0f )
				{
					CycleCounterAdjustmentMS = ProfilerFrame->Root->CycleCounterStartTimeMS;
				}

				// Update thread time and mark profiler frame as valid and ready for use.
				ProfilerFrame->MarkAsValid();
			}

			// Adjust all profiler frames.
			ProfilerStream.AdjustCycleCounters( CycleCounterAdjustmentMS );
		}
	}

	const int64 AllocatedSize = ProfilerStream.GetAllocatedSize();

	// We have the whole metadata and basic information about the raw stats file, start ticking the profiler session.
	//OnTickHandle = FTicker::GetCoreTicker().AddTicker( OnTick, 0.25f );

#if	0
	if( SessionType == EProfilerSessionTypes::OfflineRaw )
	{
		// Broadcast that a capture file has been fully processed.
		OnCaptureFileProcessed.ExecuteIfBound( GetInstanceID() );
	}
#endif // 0
}
Esempio n. 20
0
void EnsureRetrievingVTablePtrDuringCtor(const TCHAR* CtorSignature)
{
	UE_CLOG(!GIsRetrievingVTablePtr, LogCore, Fatal, TEXT("The %s constructor is for internal usage only for hot-reload purposes. Please do NOT use it."), CtorSignature);
}
Esempio n. 21
0
void FOculusInput::SendControllerEvents()
{
	const double CurrentTime = FPlatformTime::Seconds();

	// @todo: Should be made configurable and unified with other controllers handling of repeat
	const float InitialButtonRepeatDelay = 0.2f;
	const float ButtonRepeatDelay = 0.1f;
	const float AnalogButtonPressThreshold = TriggerThreshold;

	IOculusRiftPlugin& OculusRiftPlugin = IOculusRiftPlugin::Get();
	ovrSession OvrSession = OculusRiftPlugin.GetSession();
	UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: OvrSession = %p"), OvrSession);
	if (OvrSession)
	{
		ovrInputState OvrInput;
		ovrTrackingState OvrTrackingState;

		const ovrResult OvrRes = ovr_GetInputState(OvrSession, ovrControllerType_Touch, &OvrInput);
		const bool bOvrGCTRes = OculusRiftPlugin.GetCurrentTrackingState(&OvrTrackingState);

		UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: ovr_GetInputState() ret = %d, GetCurrentTrackingState ret = %d"), int(OvrRes), int(bOvrGCTRes));

		if (OvrRes == ovrSuccess && bOvrGCTRes)
		{
			UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: ConnectedControllerTypes 0x%X"), OvrInput.ConnectedControllerTypes);
			UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: ButtonState = 0x%X"), OvrInput.Buttons);
			UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: Touches = 0x%X"), OvrInput.Touches);

			for (FOculusTouchControllerPair& ControllerPair : ControllerPairs)
			{
				for( int32 HandIndex = 0; HandIndex < ARRAY_COUNT( ControllerPair.ControllerStates ); ++HandIndex )
				{
					FOculusTouchControllerState& State = ControllerPair.ControllerStates[ HandIndex ];

					const bool bIsLeft = (HandIndex == (int32)EControllerHand::Left);
					bool bIsCurrentlyTracked = (bIsLeft ? (OvrInput.ConnectedControllerTypes & ovrControllerType_LTouch) != 0 : (OvrInput.ConnectedControllerTypes & ovrControllerType_RTouch) != 0);

#if OVR_TESTING
					bIsCurrentlyTracked = true;
					static float _angle = 0;
					OvrTrackingState.HandPoses[HandIndex].ThePose.Orientation = OVR::Quatf(OVR::Vector3f(0, 0, 1), _angle);
					_angle += 0.1f;

					OvrTrackingState.HandPoses[HandIndex].ThePose = OvrTrackingState.HeadPose.ThePose;
					UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Error, TEXT("SendControllerEvents: OVR_TESTING is enabled!"));
#endif

					if (bIsCurrentlyTracked)
					{
						State.bIsCurrentlyTracked = true;

						const float OvrTriggerAxis = OvrInput.IndexTrigger[HandIndex];
						const float OvrGripAxis = OvrInput.HandTrigger[HandIndex];

						UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: IndexTrigger[%d] = %f"), int(HandIndex), OvrTriggerAxis);
						UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: HandTrigger[%d] = %f"), int(HandIndex), OvrGripAxis);
						UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: ThumbStick[%d] = { %f, %f }"), int(HandIndex), OvrInput.Thumbstick[HandIndex].x, OvrInput.Thumbstick[HandIndex].y );

						if (OvrTriggerAxis != State.TriggerAxis)
						{
							State.TriggerAxis = OvrTriggerAxis;
							MessageHandler->OnControllerAnalog(bIsLeft ? FGamepadKeyNames::MotionController_Left_TriggerAxis : FGamepadKeyNames::MotionController_Right_TriggerAxis, ControllerPair.UnrealControllerIndex, State.TriggerAxis);
						}

						if (OvrGripAxis != State.GripAxis)
						{
							State.GripAxis = OvrGripAxis;
							MessageHandler->OnControllerAnalog(bIsLeft ? FGamepadKeyNames::MotionController_Left_Grip1Axis : FGamepadKeyNames::MotionController_Right_Grip1Axis, ControllerPair.UnrealControllerIndex, State.GripAxis);
						}

						if (OvrInput.Thumbstick[HandIndex].x != State.ThumbstickAxes.X)
						{
							State.ThumbstickAxes.X = OvrInput.Thumbstick[HandIndex].x;
							MessageHandler->OnControllerAnalog(bIsLeft ? FGamepadKeyNames::MotionController_Left_Thumbstick_X : FGamepadKeyNames::MotionController_Right_Thumbstick_X, ControllerPair.UnrealControllerIndex, State.ThumbstickAxes.X);
						}

						if (OvrInput.Thumbstick[HandIndex].y != State.ThumbstickAxes.Y)
						{
							State.ThumbstickAxes.Y = OvrInput.Thumbstick[HandIndex].y;
							// we need to negate Y value to match XBox controllers
							MessageHandler->OnControllerAnalog(bIsLeft ? FGamepadKeyNames::MotionController_Left_Thumbstick_Y : FGamepadKeyNames::MotionController_Right_Thumbstick_Y, ControllerPair.UnrealControllerIndex, -State.ThumbstickAxes.Y);
						}

						for (int32 ButtonIndex = 0; ButtonIndex < (int32)EOculusTouchControllerButton::TotalButtonCount; ++ButtonIndex)
						{
							FOculusButtonState& ButtonState = State.Buttons[ButtonIndex];
							check(!ButtonState.Key.IsNone()); // is button's name initialized?

							// Determine if the button is pressed down
							bool bButtonPressed = false;
							switch ((EOculusTouchControllerButton)ButtonIndex)
							{
							case EOculusTouchControllerButton::Trigger:
								bButtonPressed = State.TriggerAxis >= AnalogButtonPressThreshold;
								break;

							case EOculusTouchControllerButton::Grip:
								bButtonPressed = State.GripAxis >= AnalogButtonPressThreshold;
								break;

							case EOculusTouchControllerButton::XA:
								bButtonPressed = bIsLeft ? (OvrInput.Buttons & ovrButton_X) != 0 : (OvrInput.Buttons & ovrButton_A) != 0;
								break;

							case EOculusTouchControllerButton::YB:
								bButtonPressed = bIsLeft ? (OvrInput.Buttons & ovrButton_Y) != 0 : (OvrInput.Buttons & ovrButton_B) != 0;
								break;

							case EOculusTouchControllerButton::Thumbstick:
								bButtonPressed = bIsLeft ? (OvrInput.Buttons & ovrButton_LThumb) != 0 : (OvrInput.Buttons & ovrButton_RThumb) != 0;
								break;

							default:
								check(0);
								break;
							}

							// Update button state
							if (bButtonPressed != ButtonState.bIsPressed)
							{
								const bool bIsRepeat = false;

								ButtonState.bIsPressed = bButtonPressed;
								if (ButtonState.bIsPressed)
								{
									MessageHandler->OnControllerButtonPressed(ButtonState.Key, ControllerPair.UnrealControllerIndex, bIsRepeat);

									// Set the timer for the first repeat
									ButtonState.NextRepeatTime = CurrentTime + ButtonRepeatDelay;
								}
								else
								{
									MessageHandler->OnControllerButtonReleased(ButtonState.Key, ControllerPair.UnrealControllerIndex, bIsRepeat);
								}
							}

							// Apply key repeat, if its time for that
							if (ButtonState.bIsPressed && ButtonState.NextRepeatTime <= CurrentTime)
							{
								const bool bIsRepeat = true;
								MessageHandler->OnControllerButtonPressed(ButtonState.Key, ControllerPair.UnrealControllerIndex, bIsRepeat);

								// Set the timer for the next repeat
								ButtonState.NextRepeatTime = CurrentTime + ButtonRepeatDelay;
							}
						}

						// Handle Capacitive States
						for (int32 CapTouchIndex = 0; CapTouchIndex < (int32)EOculusTouchCapacitiveAxes::TotalAxisCount; ++CapTouchIndex)
						{
							FOculusTouchCapacitiveState& CapState = State.CapacitiveAxes[CapTouchIndex];

							float CurrentAxisVal = 0.f;
							switch ((EOculusTouchCapacitiveAxes)CapTouchIndex)
							{
							case EOculusTouchCapacitiveAxes::XA:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_X : ovrTouch_A;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::YB:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_Y : ovrTouch_B;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::Thumbstick:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_LThumb : ovrTouch_RThumb;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::Trigger:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_LIndexTrigger : ovrTouch_RIndexTrigger;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::IndexPointing:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_LIndexPointing : ovrTouch_RIndexPointing;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::ThumbUp:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_LThumbUp : ovrTouch_RThumbUp;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							default:
								check(0);
							}
							
							if (CurrentAxisVal != CapState.State)
							{
								MessageHandler->OnControllerAnalog(CapState.Axis, ControllerPair.UnrealControllerIndex, CurrentAxisVal);

								CapState.State = CurrentAxisVal;
							}
						}

						const ovrPosef& OvrHandPose = OvrTrackingState.HandPoses[HandIndex].ThePose;
						FVector NewLocation;
						FQuat NewOrientation;
						if (OculusRiftPlugin.PoseToOrientationAndPosition(OvrHandPose, /* Out */ NewOrientation, /* Out */ NewLocation))
						{
							// OK, we have up to date positional data!
							State.Orientation = NewOrientation;
							State.Location = NewLocation;

							UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: HandPOSE[%d]: Pos %.3f %.3f %.3f"), HandIndex, NewLocation.X, NewLocation.Y, NewLocation.Y);
							UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: HandPOSE[%d]: Yaw %.3f Pitch %.3f Roll %.3f"), HandIndex, NewOrientation.Rotator().Yaw, NewOrientation.Rotator().Pitch, NewOrientation.Rotator().Roll);
						}
						else
						{
							// HMD wasn't ready.  This can currently happen if we try to grab motion data before we've rendered at least one frame
							UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: PoseToOrientationAndPosition returned false"));
						}
					}
					else
					{
						// Controller isn't available right now.  Zero out input state, so that if it comes back it will send fresh event deltas
						State = FOculusTouchControllerState((EControllerHand)HandIndex);
						UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: Controller for the hand %d is not tracked"), int(HandIndex));
					}
				}
			}
		}
	}
	UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT(""));
}
void FGearVRSplash::Show(EShowType InShowType)
{
	check(IsInGameThread());
	Hide(InShowType);

	ShowType = InShowType;

	FCustomPresent* pCustomPresent = pPlugin->GetCustomPresent_Internal();
	if (pCustomPresent)
	{
		bool ReadyToPush = IsLoadingIconMode();

		LayerMgr->RemoveAllLayers();

		// scope lock
		{
			FScopeLock ScopeLock(&SplashScreensLock);
			// Make sure all UTextures are loaded and contain Resource->TextureRHI
			bool bWaitForRT = false;
			for (int32 i = 0; i < SplashScreenDescs.Num(); ++i)
			{
				if (!SplashScreenDescs[i].TexturePath.IsEmpty())
				{
					// load temporary texture (if TexturePath was specified)
					LoadTexture(SplashScreenDescs[i]);
				}
				if (SplashScreenDescs[i].LoadingTexture->IsValidLowLevel())
				{
					SplashScreenDescs[i].LoadingTexture->UpdateResource();
					bWaitForRT = true;
				}
			}
			if (bWaitForRT)
			{
				FlushRenderingCommands();
			}
			for (int32 i = 0; i < SplashScreenDescs.Num(); ++i)
			{
				//@DBG BEGIN
				if (!SplashScreenDescs[i].LoadingTexture->IsValidLowLevel())
				{
					continue;
				}
				if (!SplashScreenDescs[i].LoadingTexture->Resource)
				{
					UE_LOG(LogHMD, Warning, TEXT("Splash, %s - no Resource"), *SplashScreenDescs[i].LoadingTexture->GetDesc());
				}
				else
				{
					UE_CLOG(!SplashScreenDescs[i].LoadingTexture->Resource->TextureRHI, LogHMD, Warning, TEXT("Splash, %s - no TextureRHI"), *SplashScreenDescs[i].LoadingTexture->GetDesc());
				}
				//@DBG END
				if (SplashScreenDescs[i].LoadingTexture->Resource && SplashScreenDescs[i].LoadingTexture->Resource->TextureRHI)
				{
					if (IsLoadingIconMode())
					{
						pPlugin->SetLoadingIconTexture(SplashScreenDescs[i].LoadingTexture->Resource->TextureRHI);
					}
					else
					{
						FRenderSplashInfo RenSplash;
						// use X (depth) as layers priority
						const uint32 Prio = FHMDLayerDesc::MaxPriority - uint32(SplashScreenDescs[i].TransformInMeters.GetTranslation().X * 1000.f);
						TSharedPtr<FHMDLayerDesc> layer = LayerMgr->AddLayer(FHMDLayerDesc::Quad, Prio, FHMDLayerManager::Layer_TorsoLocked, RenSplash.SplashLID);
						check(layer.IsValid());
						layer->SetTexture(SplashScreenDescs[i].LoadingTexture->Resource->TextureRHI);
						layer->SetTransform(SplashScreenDescs[i].TransformInMeters);
						layer->SetQuadSize(SplashScreenDescs[i].QuadSizeInMeters);

						RenSplash.Desc = SplashScreenDescs[i];

						FScopeLock ScopeLock2(&RenderSplashScreensLock);
						RenderSplashScreens.Add(RenSplash);
					}
					ReadyToPush = true;
				}
			}
		}

		// this will push black frame, if texture is not loaded

		if (ReadyToPush)
		{
			ShowingBlack = false;
			PushFrame();
		}
		else
		{
			PushBlackFrame();
		}
		pCustomPresent->LockSubmitFrame();
		UE_LOG(LogHMD, Log, TEXT("FGearVRSplash::Show"));
		SplashIsShown = true;
	}
}
void FRedirectCollector::ResolveStringAssetReference(FString FilterPackage)
{
    SCOPE_REDIRECT_TIMER(ResolveTimeTotal);


    FName FilterPackageFName = NAME_None;
    if (!FilterPackage.IsEmpty())
    {
        FilterPackageFName = FName(*FilterPackage);
    }

    TMultiMap<FName, FPackagePropertyPair> SkippedReferences;
    SkippedReferences.Empty(StringAssetReferences.Num());
    while ( StringAssetReferences.Num())
    {

        TMultiMap<FName, FPackagePropertyPair> CurrentReferences;
        Swap(StringAssetReferences, CurrentReferences);

        for (const auto& CurrentReference : CurrentReferences)
        {
            const FName& ToLoadFName = CurrentReference.Key;
            const FPackagePropertyPair& RefFilenameAndProperty = CurrentReference.Value;

            if ((FilterPackageFName != NAME_None) && // not using a filter
                    (FilterPackageFName != RefFilenameAndProperty.GetCachedPackageName()) && // this is the package we are looking for
                    (RefFilenameAndProperty.GetCachedPackageName() != NAME_None) // if we have an empty package name then process it straight away
               )
            {
                // If we have a valid filter and it doesn't match, skip this reference
                SkippedReferences.Add(ToLoadFName, RefFilenameAndProperty);
                continue;
            }

            const FString ToLoad = ToLoadFName.ToString();

            if (FCoreDelegates::LoadStringAssetReferenceInCook.IsBound())
            {
                SCOPE_REDIRECT_TIMER(ResolveTimeDelegate);
                if (FCoreDelegates::LoadStringAssetReferenceInCook.Execute(ToLoad) == false)
                {
                    // Skip this reference
                    continue;
                }
            }

            if (ToLoad.Len() > 0 )
            {
                SCOPE_REDIRECT_TIMER(ResolveTimeLoad);

                UE_LOG(LogRedirectors, Verbose, TEXT("String Asset Reference '%s'"), *ToLoad);
                UE_CLOG(RefFilenameAndProperty.GetProperty().ToString().Len(), LogRedirectors, Verbose, TEXT("    Referenced by '%s'"), *RefFilenameAndProperty.GetProperty().ToString());

                StringAssetRefFilenameStack.Push(RefFilenameAndProperty.GetPackage().ToString());

                UObject *Loaded = LoadObject<UObject>(NULL, *ToLoad, NULL, RefFilenameAndProperty.GetReferencedByEditorOnlyProperty() ? LOAD_EditorOnly : LOAD_None, NULL);
                StringAssetRefFilenameStack.Pop();

                UObjectRedirector* Redirector = dynamic_cast<UObjectRedirector*>(Loaded);
                if (Redirector)
                {
                    UE_LOG(LogRedirectors, Verbose, TEXT("    Found redir '%s'"), *Redirector->GetFullName());
                    FRedirection Redir;
                    Redir.PackageFilename = RefFilenameAndProperty.GetPackage().ToString();
                    Redir.RedirectorName = Redirector->GetFullName();
                    Redir.RedirectorPackageFilename = Redirector->GetLinker()->Filename;
                    CA_SUPPRESS(28182)
                    Redir.DestinationObjectName = Redirector->DestinationObject->GetFullName();
                    Redirections.AddUnique(Redir);
                    Loaded = Redirector->DestinationObject;
                }
                if (Loaded)
                {
                    if (FCoreUObjectDelegates::PackageLoadedFromStringAssetReference.IsBound())
                    {
                        FCoreUObjectDelegates::PackageLoadedFromStringAssetReference.Broadcast(Loaded->GetOutermost()->GetFName());
                    }
                    FString Dest = Loaded->GetPathName();
                    UE_LOG(LogRedirectors, Verbose, TEXT("    Resolved to '%s'"), *Dest);
                    if (Dest != ToLoad)
                    {
                        StringAssetRemap.Add(ToLoad, Dest);
                    }
                }
                else
                {
                    const FString Referencer = RefFilenameAndProperty.GetProperty().ToString().Len() ? RefFilenameAndProperty.GetProperty().ToString() : TEXT("Unknown");

                    int32 DotIndex = ToLoad.Find(TEXT("."));

                    FString PackageName = DotIndex != INDEX_NONE ? ToLoad.Left(DotIndex) : ToLoad;

                    if (FLinkerLoad::IsKnownMissingPackage(FName(*PackageName)) == false)
                    {
                        UE_LOG(LogRedirectors, Warning, TEXT("String Asset Reference '%s' was not found! (Referencer '%s')"), *ToLoad, *Referencer);
                    }
                }
            }

        }
    }

    check(StringAssetReferences.Num() == 0);
    // Add any skipped references back into the map for the next time this is called
    Swap(StringAssetReferences, SkippedReferences);
    // we shouldn't have any references left if we decided to resolve them all
    check((StringAssetReferences.Num() == 0) || (FilterPackageFName != NAME_None));
}
Esempio n. 24
0
//
// Construct a URL from text and an optional relative base.
//
FURL::FURL( FURL* Base, const TCHAR* TextURL, ETravelType Type )
:	Protocol	( UrlConfig.DefaultProtocol )
,	Host		( UrlConfig.DefaultHost )
,	Port		( UrlConfig.DefaultPort )
,	Map			( UGameMapsSettings::GetGameDefaultMap() )
,	Op			()
,	Portal		( UrlConfig.DefaultPortal )
,	Valid		( 1 )
{
	check(TextURL);

	if( !bDefaultsInitialized )
	{
		FURL::StaticInit();
		Protocol = UrlConfig.DefaultProtocol;
		Host = UrlConfig.DefaultHost;
		Port = UrlConfig.DefaultPort;
		Portal = UrlConfig.DefaultPortal;
	}

	// Make a copy.
	const int32 URLLength = FCString::Strlen(TextURL);
	TCHAR* TempURL = new TCHAR[URLLength+1];
	TCHAR* URL = TempURL;

	FCString::Strcpy( TempURL, URLLength + 1, TextURL );

	// Copy Base.
	if( Type==TRAVEL_Relative )
	{
		check(Base);
		Protocol = Base->Protocol;
		Host     = Base->Host;
		Map      = Base->Map;
		Portal   = Base->Portal;
		Port     = Base->Port;
	}
	if( Type==TRAVEL_Relative || Type==TRAVEL_Partial )
	{
		check(Base);
		for( int32 i=0; i<Base->Op.Num(); i++ )
		{
			new(Op)FString(Base->Op[i]);
		}
	}

	// Skip leading blanks.
	while( *URL == ' ' )
	{
		URL++;
	}

	// Options.
	TCHAR* s = HelperStrchr(URL,'?','#');
	if( s )
	{
		TCHAR OptionChar=*s, NextOptionChar=0;
		*(s++) = 0;
		do
		{
			TCHAR* t = HelperStrchr(s,'?','#');
			if( t )
			{
				NextOptionChar = *t;
				*(t++) = 0;
			}
			if( !ValidNetChar( s ) )
			{
				*this = FURL();
				Valid = 0;
				break;
			}
			if( OptionChar=='?' )
			{
				if (s && s[0] == '-')
				{
					// Remove an option if it starts with -
					s++;
					RemoveOption( s );
				}
				else
				{
					AddOption( s );
				}
			}
			else
			{
				Portal = s;
			}
			s = t;
			OptionChar = NextOptionChar;
		} while( s );
	}

	if (Valid == 1)
	{
		// Handle pure filenames & Posix paths.
		bool FarHost=0;
		bool FarMap=0;
		if( FCString::Strlen(URL)>2 && (URL[1]==':' || (URL[0]=='/' && !FPackageName::IsValidLongPackageName(URL, true))) )
		{
			// Pure filename.
			Protocol = UrlConfig.DefaultProtocol;
			Host = UrlConfig.DefaultHost;
			Map = URL;
			Portal = UrlConfig.DefaultPortal;
			URL = NULL;
			FarHost = 1;
			FarMap = 1;
			Host = TEXT("");
		}
		else
		{
			// Parse protocol.
			if
			(	(FCString::Strchr(URL,':')!=NULL)
			&&	(FCString::Strchr(URL,':')>URL+1)
			&&	(FCString::Strchr(URL,'.')==NULL || FCString::Strchr(URL,':')<FCString::Strchr(URL,'.')) )
			{
				TCHAR* ss = URL;
				URL      = FCString::Strchr(URL,':');
				*(URL++)   = 0;
				Protocol = ss;
			}

			// Parse optional leading double-slashes.
			if( *URL=='/' && *(URL+1) =='/' )
			{
				URL += 2;
				FarHost = 1;
				Host = TEXT("");
			}

			// Parse optional host name and port.
			const TCHAR* Dot = FCString::Strchr(URL,'.');
			const int32 ExtLen = FPackageName::GetMapPackageExtension().Len();

			if
			(	(Dot)
			&&	(Dot-URL>0)
			&&	(FCString::Strnicmp( Dot, *FPackageName::GetMapPackageExtension(), FPackageName::GetMapPackageExtension().Len() )!=0 || FChar::IsAlnum(Dot[ExtLen]) )
			&&	(FCString::Strnicmp( Dot+1,*UrlConfig.DefaultSaveExt, UrlConfig.DefaultSaveExt.Len() )!=0 || FChar::IsAlnum(Dot[UrlConfig.DefaultSaveExt.Len()+1]) )
			&&	(FCString::Strnicmp( Dot+1,TEXT("demo"), 4 ) != 0 || FChar::IsAlnum(Dot[5])) )
			{
				TCHAR* ss = URL;
				URL     = FCString::Strchr(URL,'/');
				if( URL )
				{
					*(URL++) = 0;
				}
				TCHAR* t = FCString::Strchr(ss,':');
				if( t )
				{
					// Port.
					*(t++) = 0;
					Port = FCString::Atoi( t );
				}
				Host = ss;
				if( FCString::Stricmp(*Protocol,*UrlConfig.DefaultProtocol)==0 )
				{
					Map = UGameMapsSettings::GetGameDefaultMap();
				}
				else
				{
					Map = TEXT("");
				}
				FarHost = 1;
			}
		}
	}

	// Parse optional map
	if (Valid == 1 && URL && *URL)
	{
		// Map.
		if (*URL != '/')
		{
			// find full pathname from short map name
			FString MapFullName;
			FText MapNameError;
			if (FPaths::FileExists(URL))
			{
				Map = FPackageName::FilenameToLongPackageName(URL);
			}
			else if (!FPackageName::DoesPackageNameContainInvalidCharacters(URL, &MapNameError) && FPackageName::SearchForPackageOnDisk(URL, &MapFullName))
			{
				Map = MapFullName;
			}
			else
			{
				// can't find file, invalidate and bail
				UE_CLOG(MapNameError.ToString().Len() > 0, LogLongPackageNames, Warning, TEXT("URL: %s: %s"), URL, *MapNameError.ToString());
				*this = FURL();
				Valid = 0;
			}
		}
		else
		{
			// already a full pathname
			Map = URL;
		}

	}
	
	// Validate everything.
	// The FarHost check does not serve any purpose I can see, and will just cause valid URLs to fail (URLs with no options, why does a URL
	// need an option to be valid?)
	if (Valid == 1 && (!ValidNetChar(*Protocol) || !ValidNetChar(*Host) /*|| !ValidNetChar(*Map)*/ || !ValidNetChar(*Portal) /*|| (!FarHost && !FarMap && !Op.Num())*/))
	{
		*this = FURL();
		Valid = 0;
	}

	// If Valid == 1, success.

	delete[] TempURL;
}
void FProfilerClientManager::LoadCapture( const FString& DataFilepath, const FGuid& ProfileId )
{
#if STATS
	// start an async load
	LoadConnection = &Connections.FindOrAdd(ProfileId);
	LoadConnection->InstanceId = ProfileId;
	LoadConnection->MetaData.CriticalSection = &LoadConnection->CriticalSection;
	LoadConnection->MetaData.SecondsPerCycle = FPlatformTime::GetSecondsPerCycle(); // fix this by adding a message which specifies this

	const int64 Size = IFileManager::Get().FileSize( *DataFilepath );
	if( Size < 4 )
	{
		UE_LOG( LogProfile, Error, TEXT( "Could not open: %s" ), *DataFilepath );
		return;
	}

#if PROFILER_THREADED_LOAD
	FArchive* FileReader = IFileManager::Get().CreateFileReader(*DataFilepath);
#else
	FileReader = IFileManager::Get().CreateFileReader( *DataFilepath );
#endif

	if( !FileReader )
	{
		UE_LOG( LogProfile, Error, TEXT( "Could not open: %s" ), *DataFilepath );
		return;
	}

	if( !LoadConnection->Stream.ReadHeader( *FileReader ) )
	{
		UE_LOG( LogProfile, Error, TEXT( "Could not open, bad magic: %s" ), *DataFilepath );
		delete FileReader;
		return;
	}

	// This shouldn't happen.
	if( LoadConnection->Stream.Header.bRawStatsFile )
	{
		delete FileReader;
		return;
	}

	const bool bIsFinalized = LoadConnection->Stream.Header.IsFinalized();
	if( bIsFinalized )
	{
		// Read metadata.
		TArray<FStatMessage> MetadataMessages;
		LoadConnection->Stream.ReadFNamesAndMetadataMessages( *FileReader, MetadataMessages );
		LoadConnection->CurrentThreadState.ProcessMetaDataOnly( MetadataMessages );

		// Read frames offsets.
		LoadConnection->Stream.ReadFramesOffsets( *FileReader );
		FileReader->Seek( LoadConnection->Stream.FramesInfo[0].FrameFileOffset );
	}

	if( LoadConnection->Stream.Header.HasCompressedData() )
	{
		UE_CLOG( !bIsFinalized, LogProfile, Fatal, TEXT( "Compressed stats file has to be finalized" ) );
	}

#if PROFILER_THREADED_LOAD
	LoadTask = new FAsyncTask<FAsyncReadWorker>(LoadConnection, FileReader);
	LoadTask->StartBackgroundTask();
#endif

	RetryTime = 0.05f;
	TickDelegateHandle = FTicker::GetCoreTicker().AddTicker(TickDelegate, RetryTime);
	ProfilerLoadStartedDelegate.Broadcast(ProfileId);
#endif
}
bool FGameplayAbilityTargetDataHandle::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
	uint8 DataNum;
	if (Ar.IsSaving())
	{
		UE_CLOG(Data.Num() > MAX_uint8, LogAbilitySystem, Warning, TEXT("Too many TargetData sources (%d!) to net serialize. Clamping to %d"), Data.Num(), MAX_uint8);
		DataNum = FMath::Min<int32>( Data.Num(), MAX_uint8 );
	}
	Ar << DataNum;
	if (Ar.IsLoading())
	{
		Data.SetNumZeroed(DataNum);
	}

	for (int32 i = 0; i < DataNum && !Ar.IsError(); ++i)
	{
		UScriptStruct* ScriptStruct = Data[i].IsValid() ? Data[i]->GetScriptStruct() : NULL;
		Ar << ScriptStruct;

		if (ScriptStruct)
		{
			if (Ar.IsLoading())
			{
				// For now, just always reset/reallocate the data when loading.
				// Longer term if we want to generalize this and use it for property replication, we should support
				// only reallocating when necessary
				check(!Data[i].IsValid());

				FGameplayAbilityTargetData * NewData = (FGameplayAbilityTargetData*)FMemory::Malloc(ScriptStruct->GetCppStructOps()->GetSize());
				ScriptStruct->InitializeStruct(NewData);

				Data[i] = TSharedPtr<FGameplayAbilityTargetData>(NewData);
			}

			void* ContainerPtr = Data[i].Get();

			if (ScriptStruct->StructFlags & STRUCT_NetSerializeNative)
			{
				ScriptStruct->GetCppStructOps()->NetSerialize(Ar, Map, bOutSuccess, Data[i].Get());
			}
			else
			{
				// This won't work since UStructProperty::NetSerializeItem is deprecrated.
				//	1) we have to manually crawl through the topmost struct's fields since we don't have a UStructProperty for it (just the UScriptProperty)
				//	2) if there are any UStructProperties in the topmost struct's fields, we will assert in UStructProperty::NetSerializeItem.

				ABILITY_LOG(Fatal, TEXT("FGameplayAbilityTargetDataHandle::NetSerialize called on data struct %s without a native NetSerialize"), *ScriptStruct->GetName());

				for (TFieldIterator<UProperty> It(ScriptStruct); It; ++It)
				{
					if (It->PropertyFlags & CPF_RepSkip)
					{
						continue;
					}

					void* PropertyData = It->ContainerPtrToValuePtr<void*>(ContainerPtr);

					It->NetSerializeItem(Ar, Map, PropertyData);
				}
			}
		}
	}

	//ABILITY_LOG(Warning, TEXT("FGameplayAbilityTargetDataHandle Serialized: %s"), ScriptStruct ? *ScriptStruct->GetName() : TEXT("NULL") );

	bOutSuccess = true;
	return true;
}
Esempio n. 27
0
bool FAutoReimportDirectoryConfig::ParseSourceDirectoryAndMountPoint(FString& SourceDirectory, FString& MountPoint, const FParseContext& InContext)
{
	SourceDirectory.ReplaceInline(TEXT("\\"), TEXT("/"));

	// Check if the source directory is actually a mount point
	if (!FPackageName::GetPackageMountPoint(SourceDirectory).IsNone())
	{
		MountPoint = SourceDirectory;
		SourceDirectory = FString();
	}

	if (!SourceDirectory.IsEmpty() && !MountPoint.IsEmpty())
	{
		// We have both a source directory and a mount point. Verify that the source dir exists, and that the mount point is valid.
		if (!IFileManager::Get().DirectoryExists(*SourceDirectory))
		{
			UE_CLOG(InContext.bEnableLogging, LogAutoReimportManager, Warning, TEXT("Unable to watch directory %s as it doesn't exist."), *SourceDirectory);
			return false;
		}

		if (FPackageName::GetPackageMountPoint(MountPoint).IsNone())
		{
			UE_CLOG(InContext.bEnableLogging, LogAutoReimportManager, Warning, TEXT("Unable to setup directory %s to map to %s, as it's not a valid mounted path. Continuing without mounted path (auto reimports will still work, but auto add won't)."), *SourceDirectory, *MountPoint);
		}
	}
	else if(!MountPoint.IsEmpty())
	{
		// We have just a mount point - validate it, and find its source directory
		if (FPackageName::GetPackageMountPoint(MountPoint).IsNone())
		{
			UE_CLOG(InContext.bEnableLogging, LogAutoReimportManager, Warning, TEXT("Unable to setup directory monitor for %s, as it's not a valid mounted path."), *MountPoint);
			return false;
		}

		SourceDirectory = FPackageName::LongPackageNameToFilename(MountPoint);
	}
	else if(!SourceDirectory.IsEmpty())
	{
		// We have just a source directory - verify whether it's a mounted path, and set up the mount point if so
		if (!IFileManager::Get().DirectoryExists(*SourceDirectory))
		{
			UE_CLOG(InContext.bEnableLogging, LogAutoReimportManager, Warning, TEXT("Unable to watch directory %s as it doesn't exist."), *SourceDirectory);
			return false;
		}

		// Set the mounted path if necessary
		auto* Pair = InContext.MountedPaths.FindByPredicate([&](const TPair<FString, FString>& InPair){
			return SourceDirectory.StartsWith(InPair.Key);
		});

		if (Pair)
		{
			MountPoint = Pair->Value / SourceDirectory.RightChop(Pair->Key.Len());
			MountPoint.ReplaceInline(TEXT("\\"), TEXT("/"));
		}
	}
	else
	{
		// Don't have any valid settings
		return false;
	}

	return true;
}