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; }
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 }
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 } }
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(); } } } } }
/** * 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; }
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; }
/** * 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(); }
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; }
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; }
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 }
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); }
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)); }
// // 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; }
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; }