int32 FMessageTracer::GetMessageTypes( TArray<FMessageTracerTypeInfoPtr>& OutTypes ) const { MessageTypes.GenerateValueArray(OutTypes); return OutTypes.Num(); }
bool FAutomationTestFramework::RunSmokeTests() { bool bAllSuccessful = true; //so extra log spam isn't generated bRunningSmokeTests = true; // Skip running on cooked platforms like mobile //@todo - better determination of whether to run than requires cooked data // Ensure there isn't another slow task in progress when trying to run unit tests const bool bRequiresCookedData = FPlatformProperties::RequiresCookedData(); if ((!bRequiresCookedData && !GIsSlowTask && !GIsPlayInEditorWorld) || bForceSmokeTests) { TArray<FAutomationTestInfo> TestInfo; GetValidTestNames( TestInfo ); if ( TestInfo.Num() > 0 ) { double SmokeTestStartTime = FPlatformTime::Seconds(); // Output the results of running the automation tests TMap<FString, FAutomationTestExecutionInfo> OutExecutionInfoMap; // Run each valid test FScopedSlowTask SlowTask(TestInfo.Num()); for ( int TestIndex = 0; TestIndex < TestInfo.Num(); ++TestIndex ) { SlowTask.EnterProgressFrame(1); if (TestInfo[TestIndex].GetTestType() == EAutomationTestType::ATT_SmokeTest ) { FString TestCommand = TestInfo[TestIndex].GetTestName(); FAutomationTestExecutionInfo& CurExecutionInfo = OutExecutionInfoMap.Add( TestCommand, FAutomationTestExecutionInfo() ); int32 RoleIndex = 0; //always default to "local" role index. Only used for multi-participant tests StartTestByName( TestCommand, RoleIndex ); const bool CurTestSuccessful = StopTest(CurExecutionInfo); bAllSuccessful = bAllSuccessful && CurTestSuccessful; } } double EndTime = FPlatformTime::Seconds(); double TimeForTest = static_cast<float>(EndTime - SmokeTestStartTime); if (TimeForTest > 1.0f) { //force a failure if a smoke test takes too long UE_LOG(LogAutomationTest, Warning, TEXT("Smoke tests took > 1s to run: %.2fs"), (float)TimeForTest); } FAutomationTestFramework::DumpAutomationTestExecutionInfo( OutExecutionInfoMap ); } } else if( bRequiresCookedData ) { UE_LOG( LogAutomationTest, Log, TEXT( "Skipping unit tests for the cooked build." ) ); } else { UE_LOG(LogAutomationTest, Error, TEXT("Skipping unit tests.") ); bAllSuccessful = false; } //revert to allowing all logs bRunningSmokeTests = false; return bAllSuccessful; }
void FSpriteDetailsCustomization::BuildRenderingSection(IDetailCategoryBuilder& RenderingCategory, IDetailLayoutBuilder& DetailLayout) { TAttribute<EVisibility> HideWhenInCollisionMode = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::EditorModeIsNot, ESpriteEditorMode::EditCollisionMode)); TAttribute<EVisibility> ShowWhenInCollisionMode = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::EditorModeMatches, ESpriteEditorMode::EditCollisionMode)); static const FText EditRenderingInRenderingMode = LOCTEXT("RenderingPropertiesHiddenInCollisionMode", "Switch to 'Edit RenderGeom' mode\nto edit Rendering settings"); RenderingCategory.AddCustomRow(EditRenderingInRenderingMode) .Visibility(ShowWhenInCollisionMode) .WholeRowContent() .HAlign(HAlign_Center) [ SNew(STextBlock) .Font(DetailLayout.GetDetailFontItalic()) .Justification(ETextJustify::Center) .Text(EditRenderingInRenderingMode) ]; TArray<TWeakObjectPtr<UObject>> ObjectsBeingCustomized; DetailLayout.GetObjectsBeingCustomized(/*out*/ ObjectsBeingCustomized); if (ObjectsBeingCustomized.Num() > 0) { if (UPaperSprite* SpriteBeingEdited = Cast<UPaperSprite>(ObjectsBeingCustomized[0].Get())) { static const FText TypesOfMaterialsTooltip = LOCTEXT("TypesOfMaterialsTooltip", "Translucent materials can have smooth alpha edges, blending with the background\nMasked materials have on or off alpha, useful for cutouts\nOpaque materials have no transparency but render faster"); RenderingCategory.HeaderContent ( SNew(SBox) .HAlign(HAlign_Right) [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .Padding(FMargin(5.0f, 0.0f)) .AutoWidth() [ SNew(STextBlock) .Font(FEditorStyle::GetFontStyle("TinyText")) .Text(this, &FSpriteDetailsCustomization::GetRenderingHeaderContentText, TWeakObjectPtr<UPaperSprite>(SpriteBeingEdited)) .ToolTipText(TypesOfMaterialsTooltip) ] ] ); } } // Add the rendering geometry mode into the parent container (renamed) const FString RenderGeometryTypePropertyPath = FString::Printf(TEXT("%s.%s"), GET_MEMBER_NAME_STRING_CHECKED(UPaperSprite, RenderGeometry), GET_MEMBER_NAME_STRING_CHECKED(FSpriteGeometryCollection, GeometryType)); TSharedPtr<IPropertyHandle> RenderGeometryTypeProperty = DetailLayout.GetProperty(*RenderGeometryTypePropertyPath); RenderingCategory.AddProperty(RenderGeometryTypeProperty) .DisplayName(LOCTEXT("RenderGeometryType", "Render Geometry Type")) .Visibility(HideWhenInCollisionMode); // Show the alternate material, but only when the mode is Diced TAttribute<EVisibility> ShowWhenModeIsDiced = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::PolygonModeMatches, RenderGeometryTypeProperty, ESpritePolygonMode::Diced)); TSharedPtr<IPropertyHandle> AlternateMaterialProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, AlternateMaterial)); RenderingCategory.AddProperty(AlternateMaterialProperty) .Visibility(ShowWhenModeIsDiced); // Show the rendering geometry settings TSharedRef<IPropertyHandle> RenderGeometry = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, RenderGeometry)); IDetailPropertyRow& RenderGeometryProperty = RenderingCategory.AddProperty(RenderGeometry) .Visibility(HideWhenInCollisionMode); // Add the render polygons into advanced (renamed) const FString RenderGeometryPolygonsPropertyPath = FString::Printf(TEXT("%s.%s"), GET_MEMBER_NAME_STRING_CHECKED(UPaperSprite, RenderGeometry), GET_MEMBER_NAME_STRING_CHECKED(FSpriteGeometryCollection, Shapes)); RenderingCategory.AddProperty(DetailLayout.GetProperty(*RenderGeometryPolygonsPropertyPath), EPropertyLocation::Advanced) .DisplayName(LOCTEXT("RenderShapes", "Render Shapes")) .Visibility(HideWhenInCollisionMode); }
void FAssetFixUpRedirectors::LoadReferencingPackages(TArray<FRedirectorRefs>& RedirectorsToFix, TArray<UPackage*>& OutReferencingPackagesToSave) const { FScopedSlowTask SlowTask( RedirectorsToFix.Num(), LOCTEXT( "LoadingReferencingPackages", "Loading Referencing Packages..." ) ); SlowTask.MakeDialog(); ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider(); // Load all packages that reference each redirector, if possible for ( auto RedirectorRefsIt = RedirectorsToFix.CreateIterator(); RedirectorRefsIt; ++RedirectorRefsIt ) { SlowTask.EnterProgressFrame(1); FRedirectorRefs& RedirectorRefs = *RedirectorRefsIt; if ( ISourceControlModule::Get().IsEnabled() ) { FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(RedirectorRefs.Redirector->GetOutermost(), EStateCacheUsage::Use); const bool bValidSCCState = !SourceControlState.IsValid() || SourceControlState->IsAdded() || SourceControlState->IsCheckedOut() || SourceControlState->CanCheckout() || !SourceControlState->IsSourceControlled() || SourceControlState->IsIgnored(); if ( !bValidSCCState ) { RedirectorRefs.bRedirectorValidForFixup = false; RedirectorRefs.FailureReason = LOCTEXT("RedirectorFixupFailed_BadSCC", "Redirector could not be checked out or marked for delete"); } } // Load all referencers for ( auto PackageNameIt = RedirectorRefs.ReferencingPackageNames.CreateConstIterator(); PackageNameIt; ++PackageNameIt ) { const FString PackageName = (*PackageNameIt).ToString(); // Find the package in memory. If it is not in memory, try to load it UPackage* Package = FindPackage(NULL, *PackageName); if ( !Package ) { // Check if the package is a map before loading it! if ( FEditorFileUtils::IsMapPackageAsset(PackageName) ) { // This reference was a map package, don't load it RedirectorRefs.bRedirectorValidForFixup = false; RedirectorRefs.FailureReason = FText::Format(LOCTEXT("RedirectorFixupFailed_MapReference", "Redirector is referenced by an unloaded map. Package: {0}"), FText::FromString(PackageName)); continue; } Package = LoadPackage(NULL, *PackageName, LOAD_None); } if ( Package ) { if ( Package->PackageFlags & PKG_CompiledIn ) { // This is a script reference RedirectorRefs.bRedirectorValidForFixup = false; RedirectorRefs.FailureReason = FText::Format(LOCTEXT("RedirectorFixupFailed_CodeReference", "Redirector is referenced by code. Package: {0}"), FText::FromString(PackageName)); } else { // If we found a valid package, mark it for save OutReferencingPackagesToSave.AddUnique(Package); } } } } }
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; }
int32 UUpdateGameProjectCommandlet::Main( const FString& InParams ) { // Parse command line. TArray<FString> Tokens; TArray<FString> Switches; UCommandlet::ParseCommandLine(*InParams, Tokens, Switches); FString Category; FText ChangelistDescription = NSLOCTEXT("UpdateGameProjectCmdlet", "ChangelistDescription", "Updated game project"); bool bAutoCheckout = false; bool bAutoSubmit = false; bool bSignSampleProject = false; const FString CategorySwitch = TEXT("Category="); const FString ChangelistDescriptionSwitch = TEXT("ChangelistDescription="); for ( int32 SwitchIdx = 0; SwitchIdx < Switches.Num(); ++SwitchIdx ) { const FString& Switch = Switches[SwitchIdx]; if ( Switch == TEXT("AutoCheckout") ) { bAutoCheckout = true; } else if ( Switch == TEXT("AutoSubmit") ) { bAutoSubmit = true; } else if ( Switch == TEXT("SignSampleProject") ) { bSignSampleProject = true; } else if ( Switch.StartsWith(CategorySwitch) ) { Category = Switch.Mid( CategorySwitch.Len() ); } else if ( Switch.StartsWith(ChangelistDescriptionSwitch) ) { ChangelistDescription = FText::FromString( Switch.Mid( ChangelistDescriptionSwitch.Len() ) ); } } if ( !FPaths::IsProjectFilePathSet() ) { UE_LOG(LogUpdateGameProjectCommandlet, Error, TEXT("You must launch with a project file to be able to update it")); return 1; } const FString ProjectFilePath = FPaths::GetProjectFilePath(); ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider(); if ( bAutoCheckout ) { SourceControlProvider.Init(); } FString EngineIdentifier = GEngineVersion.ToString(EVersionComponent::Minor); UE_LOG(LogUpdateGameProjectCommandlet, Display, TEXT("Updating project file %s to %s..."), *ProjectFilePath, *EngineIdentifier); FText FailReason; if ( !FGameProjectGenerationModule::Get().UpdateGameProject(ProjectFilePath, EngineIdentifier, FailReason) ) { UE_LOG(LogUpdateGameProjectCommandlet, Error, TEXT("Couldn't update game project: %s"), *FailReason.ToString()); return 1; } if ( bSignSampleProject ) { UE_LOG(LogUpdateGameProjectCommandlet, Display, TEXT("Attempting to sign project file %s..."), *ProjectFilePath); FText LocalFailReason; if ( IProjectManager::Get().SignSampleProject(ProjectFilePath, Category, LocalFailReason) ) { UE_LOG(LogUpdateGameProjectCommandlet, Display, TEXT("Signed project file %s saved."), *ProjectFilePath); } else { UE_LOG(LogUpdateGameProjectCommandlet, Warning, TEXT("%s"), *LocalFailReason.ToString()); } } if ( bAutoSubmit ) { if ( !bAutoCheckout ) { // We didn't init SCC above so do it now SourceControlProvider.Init(); } if ( ISourceControlModule::Get().IsEnabled() ) { const FString AbsoluteFilename = FPaths::ConvertRelativePathToFull(FPaths::GetProjectFilePath()); FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate); if ( SourceControlState.IsValid() && SourceControlState->IsCheckedOut() ) { TSharedRef<FCheckIn, ESPMode::ThreadSafe> CheckInOperation = ISourceControlOperation::Create<FCheckIn>(); CheckInOperation->SetDescription(ChangelistDescription); SourceControlProvider.Execute(CheckInOperation, AbsoluteFilename); } } } return 0; }
TSharedPtr<FPropertyNode> FDetailLayoutBuilderImpl::GetPropertyNodeInternal( const FName PropertyPath, const UClass* ClassOutermost, FName InstanceName ) const { FName PropertyName; TArray<FString> PathList; PropertyPath.ToString().ParseIntoArray( &PathList, TEXT("."), true ); if( PathList.Num() == 1 ) { PropertyName = FName( *PathList[0] ); } // The class to find properties in defaults to the class currently being customized FName ClassName = CurrentCustomizationClass ? CurrentCustomizationClass->GetFName() : NAME_None; if( ClassOutermost != NULL ) { // The requested a different class ClassName = ClassOutermost->GetFName(); } // Find the outer variable name. This only matters if there are multiple instances of the same property FName OuterVariableName = CurrentCustomizationVariableName; if( InstanceName != NAME_None ) { OuterVariableName = InstanceName; } // If this fails there are no properties associated with the class name provided FClassInstanceToPropertyMap* ClassInstanceToPropertyMapPtr = PropertyMap.Find( ClassName ); if( ClassInstanceToPropertyMapPtr ) { FClassInstanceToPropertyMap& ClassInstanceToPropertyMap = *ClassInstanceToPropertyMapPtr; if( OuterVariableName == NAME_None && ClassInstanceToPropertyMap.Num() == 1 ) { // If the outer variable name still wasnt specified and there is only one instance, just use that auto FirstKey = ClassInstanceToPropertyMap.CreateIterator(); OuterVariableName = FirstKey.Key(); } FPropertyNodeMap* PropertyNodeMapPtr = ClassInstanceToPropertyMap.Find( OuterVariableName ); if( PropertyNodeMapPtr ) { FPropertyNodeMap& PropertyNodeMap = *PropertyNodeMapPtr; // Check for property name fast path first if( PropertyName != NAME_None ) { // The property name was ambiguous or not found if this fails. If ambiguous, it means there are multiple data same typed data structures(components or structs) in the class which // causes multiple properties by the same name to exist. These properties must be found via the path method. return PropertyNodeMap.PropertyNameToNode.FindRef( PropertyName ); } else { // We need to search through the tree for a property with the given path TSharedPtr<FPropertyNode> PropertyNode; // Path should be in the format A[optional_index].B.C if( PathList.Num() ) { // Get the base property and index FString Property; int32 Index; GetPropertyAndIndex( PathList[0], Property, Index ); // Get the parent most property node which is the one in the map. Its children need to be searched PropertyNode = PropertyNodeMap.PropertyNameToNode.FindRef( FName( *Property ) ); if( PropertyNode.IsValid() ) { if( Index != INDEX_NONE ) { // The parent is the actual array, its children are array elements PropertyNode = PropertyNode->GetChildNode( Index ); } // Search any additional paths for the child for( int32 PathIndex = 1; PathIndex < PathList.Num(); ++PathIndex ) { GetPropertyAndIndex( PathList[PathIndex], Property, Index ); PropertyNode = FindChildPropertyNode( *PropertyNode, Property, Index ); } } } return PropertyNode; } } } return NULL; }
bool UWorld::ComponentOverlapTest(class UPrimitiveComponent* PrimComp, const FVector& Pos, const FRotator& Rot, const struct FComponentQueryParams& Params) const { if(GetPhysicsScene() == NULL) { return false; } if(PrimComp == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentOverlapMulti : No PrimComp")); return false; } // if target is skeletalmeshcomponent and do not support singlebody physics, we don't support this yet // talk to @JG, SP, LH if ( !PrimComp->ShouldTrackOverlaps() ) { UE_LOG(LogCollision, Log, TEXT("ComponentOverlapMulti : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName()); return false; } #if WITH_PHYSX ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType(); PxRigidActor* PRigidActor = PrimComp->BodyInstance.GetPxRigidActor(); if(PRigidActor == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentOverlapMulti : (%s) No physics data"), *PrimComp->GetPathName()); return false; } // calculate the test global pose of the actor PxTransform PTestGlobalPose = U2PTransform(FTransform(Rot, Pos)); // Get all the shapes from the actor TArray<PxShape*, TInlineAllocator<8>> PShapes; PShapes.AddZeroed(PRigidActor->getNbShapes()); int32 NumShapes = PRigidActor->getShapes(PShapes.GetData(), PShapes.Num()); // Iterate over each shape for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++) { PxShape* PShape = PShapes[ShapeIdx]; check(PShape); // Calc shape global pose PxTransform PLocalPose = PShape->getLocalPose(); PxTransform PShapeGlobalPose = PTestGlobalPose.transform(PLocalPose); GET_GEOMETRY_FROM_SHAPE(PGeom, PShape); if(PGeom != NULL) { if( GeomOverlapTest(this, *PGeom, PShapeGlobalPose, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()))) { // in this test, it only matters true or false. // if we found first true, we don't care next test anymore. return true; } } } #endif //WITH_PHYSX return false; }
bool UWorld::ComponentSweepSingle(struct FHitResult& OutHit,class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FRotator& Rot, const struct FComponentQueryParams& Params) const { OutHit.TraceStart = Start; OutHit.TraceEnd = End; if(GetPhysicsScene() == NULL) { return false; } if(PrimComp == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepSingle : No PrimComp")); return false; } // if target is skeletalmeshcomponent and do not support singlebody physics if ( !PrimComp->ShouldTrackOverlaps() ) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepSingle : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName()); return false; } ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType(); #if WITH_PHYSX // if extent is 0, do line trace if (PrimComp->IsZeroExtent()) { return RaycastSingle(this, OutHit, Start, End, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())); } PxRigidActor* PRigidActor = PrimComp->BodyInstance.GetPxRigidActor(); if(PRigidActor == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) No physics data"), *PrimComp->GetPathName()); return false; } // Get all the shapes from the actor TArray<PxShape*, TInlineAllocator<8>> PShapes; PShapes.AddZeroed(PRigidActor->getNbShapes()); int32 NumShapes = PRigidActor->getShapes(PShapes.GetData(), PShapes.Num()); // calculate the test global pose of the actor PxTransform PGlobalStartPose = U2PTransform(FTransform(Start)); PxTransform PGlobalEndPose = U2PTransform(FTransform(End)); bool bHaveBlockingHit = false; PxQuat PGeomRot = U2PQuat(Rot.Quaternion()); // Iterate over each shape for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++) { PxShape* PShape = PShapes[ShapeIdx]; check(PShape); // Calc shape global pose PxTransform PLocalShape = PShape->getLocalPose(); PxTransform PShapeGlobalStartPose = PGlobalStartPose.transform(PLocalShape); PxTransform PShapeGlobalEndPose = PGlobalEndPose.transform(PLocalShape); // consider localshape rotation for shape rotation PxQuat PShapeRot = PGeomRot * PLocalShape.q; GET_GEOMETRY_FROM_SHAPE(PGeom, PShape); if(PGeom != NULL) { // @todo UE4, this might not be the best behavior. If we're looking for the most closest, this have to change to save the result, and find the closest one or // any other options, right now if anything hits first, it will return if (GeomSweepSingle(this, *PGeom, PShapeRot, OutHit, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()))) { bHaveBlockingHit = true; break; } } } return bHaveBlockingHit; #endif //WITH_PHYSX return false; }
/** * Attempts to apply the material to the specified actor. * * @param TargetActor the actor to apply the material to * @param MaterialToApply the material to apply to the actor * @param OptionalMaterialSlot the material slot to apply to. * * @return true if the material was successfully applied to the actor */ bool FActorFactoryAssetProxy::ApplyMaterialToActor( AActor* TargetActor, UMaterialInterface* MaterialToApply, int32 OptionalMaterialSlot ) { bool bResult = false; if ( TargetActor != NULL && MaterialToApply != NULL ) { ALandscapeProxy* Landscape = Cast<ALandscapeProxy>(TargetActor); if (Landscape != NULL) { UProperty* MaterialProperty = FindField<UProperty>(ALandscapeProxy::StaticClass(), "LandscapeMaterial"); Landscape->PreEditChange(MaterialProperty); Landscape->LandscapeMaterial = MaterialToApply; FPropertyChangedEvent PropertyChangedEvent(MaterialProperty); Landscape->PostEditChangeProperty(PropertyChangedEvent); bResult = true; } else { TArray<UActorComponent*> EditableComponents; FActorEditorUtils::GetEditableComponents( TargetActor, EditableComponents ); // Some actors could potentially have multiple mesh components, so we need to store all of the potentially valid ones // (or else perform special cases with IsA checks on the target actor) TArray<USceneComponent*> FoundMeshComponents; // Find which mesh the user clicked on first. TInlineComponentArray<USceneComponent*> SceneComponents; TargetActor->GetComponents(SceneComponents); for ( int32 ComponentIdx=0; ComponentIdx < SceneComponents.Num(); ComponentIdx++ ) { USceneComponent* SceneComp = SceneComponents[ComponentIdx]; // Only apply the material to editable components. Components which are not exposed are not intended to be changed. if( EditableComponents.Contains( SceneComp ) ) { UMeshComponent* MeshComponent = Cast<UMeshComponent>(SceneComp); if((MeshComponent && MeshComponent->IsRegistered()) || SceneComp->IsA<UDecalComponent>()) { // Intentionally do not break the loop here, as there could be potentially multiple mesh components FoundMeshComponents.AddUnique( SceneComp ); } } } if ( FoundMeshComponents.Num() > 0 ) { // Check each component that was found for ( TArray<USceneComponent*>::TConstIterator MeshCompIter( FoundMeshComponents ); MeshCompIter; ++MeshCompIter ) { USceneComponent* SceneComp = *MeshCompIter; bResult = FComponentEditorUtils::AttemptApplyMaterialToComponent(SceneComp, MaterialToApply, OptionalMaterialSlot); } } } } return bResult; }
void ASimModeWorldMultiRotor::setupVehiclesAndCamera(std::vector<VehiclePtr>& vehicles) { //get player controller APlayerController* player_controller = this->GetWorld()->GetFirstPlayerController(); FTransform actor_transform = player_controller->GetActorTransform(); //put camera little bit above vehicle FTransform camera_transform(actor_transform.GetLocation() + FVector(-300, 0, 200)); //we will either find external camera if it already exist in evironment or create one APIPCamera* external_camera; //find all BP camera directors in the environment { TArray<AActor*> camera_dirs; UAirBlueprintLib::FindAllActor<ACameraDirector>(this, camera_dirs); if (camera_dirs.Num() == 0) { //create director FActorSpawnParameters camera_spawn_params; camera_spawn_params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; CameraDirector = this->GetWorld()->SpawnActor<ACameraDirector>(camera_director_class_, camera_transform, camera_spawn_params); spawned_actors_.Add(CameraDirector); //create external camera required for the director external_camera = this->GetWorld()->SpawnActor<APIPCamera>(external_camera_class_, camera_transform, camera_spawn_params); spawned_actors_.Add(external_camera); } else { CameraDirector = static_cast<ACameraDirector*>(camera_dirs[0]); external_camera = CameraDirector->getExternalCamera(); } } //find all vehicle pawns { TArray<AActor*> pawns; UAirBlueprintLib::FindAllActor<TMultiRotorPawn>(this, pawns); //if no vehicle pawns exists in environment if (pawns.Num() == 0) { //create vehicle pawn FActorSpawnParameters pawn_spawn_params; pawn_spawn_params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; TMultiRotorPawn* spawned_pawn = this->GetWorld()->SpawnActor<TMultiRotorPawn>( vehicle_pawn_class_, actor_transform, pawn_spawn_params); spawned_actors_.Add(spawned_pawn); pawns.Add(spawned_pawn); } //set up vehicle pawns for (AActor* pawn : pawns) { //initialize each vehicle pawn we found TMultiRotorPawn* vehicle_pawn = static_cast<TMultiRotorPawn*>(pawn); vehicle_pawn->initializeForBeginPlay(); //chose first pawn as FPV if none is designated as FPV VehiclePawnWrapper* wrapper = vehicle_pawn->getVehiclePawnWrapper(); if (enable_collision_passthrough) wrapper->config.enable_passthrough_on_collisions = true; if (wrapper->config.is_fpv_vehicle || fpv_vehicle_pawn_wrapper_ == nullptr) fpv_vehicle_pawn_wrapper_ = wrapper; //now create the connector for each pawn auto vehicle = createVehicle(wrapper); if (vehicle != nullptr) { vehicles.push_back(vehicle); if (fpv_vehicle_pawn_wrapper_ == wrapper) fpv_vehicle_connector_ = vehicle; } //else we don't have vehicle for this pawn } } CameraDirector->initializeForBeginPlay(getInitialViewMode(), fpv_vehicle_pawn_wrapper_, external_camera); }
FSelectedActorInfo BuildSelectedActorInfo( const TArray<AActor*>& SelectedActors) { FSelectedActorInfo ActorInfo; if( SelectedActors.Num() > 0 ) { // Get the class type of the first actor. AActor* FirstActor = SelectedActors[0]; if( FirstActor && !FirstActor->HasAnyFlags( RF_ClassDefaultObject ) ) { UClass* FirstClass = FirstActor->GetClass(); UObject* FirstArchetype = FirstActor->GetArchetype(); ActorInfo.bAllSelectedAreBrushes = Cast< ABrush >( FirstActor ) != NULL; ActorInfo.SelectionClass = FirstClass; // Compare all actor types with the baseline. for ( int32 ActorIndex = 0; ActorIndex < SelectedActors.Num(); ++ActorIndex ) { AActor* CurrentActor = SelectedActors[ ActorIndex ]; if( CurrentActor->HasAnyFlags( RF_ClassDefaultObject ) ) { continue; } ABrush* Brush = Cast< ABrush >( CurrentActor ); if( !Brush) { ActorInfo.bAllSelectedAreBrushes = false; } else { if( !ActorInfo.bHaveBuilderBrush ) { ActorInfo.bHaveBuilderBrush = FActorEditorUtils::IsABuilderBrush(Brush); } ActorInfo.bHaveBrush |= true; ActorInfo.bHaveBSPBrush |= (!Brush->IsVolumeBrush()); ActorInfo.bHaveVolume |= Brush->IsVolumeBrush(); } UClass* CurrentClass = CurrentActor->GetClass(); if( FirstClass != CurrentClass ) { ActorInfo.bAllSelectedActorsOfSameType = false; ActorInfo.SelectionClass = NULL; FirstClass = NULL; } else { ActorInfo.SelectionClass = CurrentActor->GetClass(); } ++ActorInfo.NumSelected; if( ActorInfo.bAllSelectedActorsBelongToCurrentLevel ) { if( !CurrentActor->GetOuter()->IsA(ULevel::StaticClass()) || !CurrentActor->GetLevel()->IsCurrentLevel() ) { ActorInfo.bAllSelectedActorsBelongToCurrentLevel = false; } } if( ActorInfo.bAllSelectedActorsBelongToSameWorld ) { if ( !ActorInfo.SharedWorld ) { ActorInfo.SharedWorld = CurrentActor->GetWorld(); check(ActorInfo.SharedWorld); } else { if( ActorInfo.SharedWorld != CurrentActor->GetWorld() ) { ActorInfo.bAllSelectedActorsBelongToCurrentLevel = false; ActorInfo.SharedWorld = NULL; } } } // To prevent move to other level for Landscape if its components are distributed in streaming levels if (CurrentActor->IsA(ALandscape::StaticClass())) { ALandscape* Landscape = CastChecked<ALandscape>(CurrentActor); if (!Landscape || !Landscape->HasAllComponent()) { if( !ActorInfo.bAllSelectedActorsBelongToCurrentLevel ) { ActorInfo.bAllSelectedActorsBelongToCurrentLevel = true; } } } if ( ActorInfo.bSelectedActorsBelongToSameLevel ) { ULevel* ActorLevel = CurrentActor->GetOuter()->IsA(ULevel::StaticClass()) ? CurrentActor->GetLevel() : NULL; if ( !ActorInfo.SharedLevel ) { // This is the first selected actor we've encountered. ActorInfo.SharedLevel = ActorLevel; } else { // Does this actor's level match the others? if ( ActorInfo.SharedLevel != ActorLevel ) { ActorInfo.bSelectedActorsBelongToSameLevel = false; ActorInfo.SharedLevel = NULL; } } } AGroupActor* FoundGroup = Cast<AGroupActor>(CurrentActor); if(!FoundGroup) { FoundGroup = AGroupActor::GetParentForActor(CurrentActor); } if( FoundGroup ) { if( !ActorInfo.bHaveSelectedSubGroup ) { ActorInfo.bHaveSelectedSubGroup = AGroupActor::GetParentForActor(FoundGroup) != NULL; } if( !ActorInfo.bHaveSelectedLockedGroup ) { ActorInfo.bHaveSelectedLockedGroup = FoundGroup->IsLocked(); } if( !ActorInfo.bHaveSelectedUnlockedGroup ) { AGroupActor* FoundRoot = AGroupActor::GetRootForActor(CurrentActor); ActorInfo.bHaveSelectedUnlockedGroup = !FoundGroup->IsLocked() || ( FoundRoot && !FoundRoot->IsLocked() ); } } else { ++ActorInfo.NumSelectedUngroupedActors; } USceneComponent* RootComp = CurrentActor->GetRootComponent(); if(RootComp != NULL && RootComp->AttachParent != NULL) { ActorInfo.bHaveAttachedActor = true; } TInlineComponentArray<UActorComponent*> ActorComponents; CurrentActor->GetComponents(ActorComponents); for( UActorComponent* Component : ActorComponents ) { if( UStaticMeshComponent* SMComp = Cast<UStaticMeshComponent>(Component) ) { if( SMComp->IsRegistered() ) { ActorInfo.bHaveStaticMeshComponent = true; } } // Check for experimental/early-access classes in the component hierarchy bool bIsExperimental, bIsEarlyAccess; FObjectEditorUtils::GetClassDevelopmentStatus(Component->GetClass(), bIsExperimental, bIsEarlyAccess); ActorInfo.bHaveExperimentalClass |= bIsExperimental; ActorInfo.bHaveEarlyAccessClass |= bIsEarlyAccess; } // Check for experimental/early-access classes in the actor hierarchy { bool bIsExperimental, bIsEarlyAccess; FObjectEditorUtils::GetClassDevelopmentStatus(CurrentClass, bIsExperimental, bIsEarlyAccess); ActorInfo.bHaveExperimentalClass |= bIsExperimental; ActorInfo.bHaveEarlyAccessClass |= bIsEarlyAccess; } if( CurrentActor->IsA( ALight::StaticClass() ) ) { ActorInfo.bHaveLight = true; } if( CurrentActor->IsA( AStaticMeshActor::StaticClass() ) ) { ActorInfo.bHaveStaticMesh = true; AStaticMeshActor* StaticMeshActor = CastChecked<AStaticMeshActor>( CurrentActor ); if ( StaticMeshActor->GetStaticMeshComponent() ) { UStaticMesh* StaticMesh = StaticMeshActor->GetStaticMeshComponent()->StaticMesh; ActorInfo.bAllSelectedStaticMeshesHaveCollisionModels &= ( (StaticMesh && StaticMesh->BodySetup) ? true : false ); } } if( CurrentActor->IsA( ASkeletalMeshActor::StaticClass() ) ) { ActorInfo.bHaveSkeletalMesh = true; } if( CurrentActor->IsA( APawn::StaticClass() ) ) { ActorInfo.bHavePawn = true; } if( CurrentActor->IsA( AEmitter::StaticClass() ) ) { ActorInfo.bHaveEmitter = true; } if ( CurrentActor->IsA( AMatineeActor::StaticClass() ) ) { ActorInfo.bHaveMatinee = true; } if ( CurrentActor->IsTemporarilyHiddenInEditor() ) { ActorInfo.bHaveHidden = true; } if ( CurrentActor->IsA( ALandscapeProxy::StaticClass() ) ) { ActorInfo.bHaveLandscape = true; } // Find our counterpart actor AActor* EditorWorldActor = EditorUtilities::GetEditorWorldCounterpartActor( CurrentActor ); if( EditorWorldActor != NULL ) { // Just count the total number of actors with counterparts ++ActorInfo.NumSimulationChanges; } } if( ActorInfo.SelectionClass != NULL ) { ActorInfo.SelectionStr = ActorInfo.SelectionClass->GetName(); } else { ActorInfo.SelectionStr = TEXT("Actor"); } } } // hack when only BSP is selected if( ActorInfo.SharedWorld == nullptr ) { ActorInfo.SharedWorld = GWorld; } return ActorInfo; }
void CompileShader_Metal(const FShaderCompilerInput& Input,FShaderCompilerOutput& Output,const FString& WorkingDirectory) { FString PreprocessedShader; FShaderCompilerDefinitions AdditionalDefines; EHlslCompileTarget HlslCompilerTarget = HCT_FeatureLevelES3_1; AdditionalDefines.SetDefine(TEXT("IOS"), 1); AdditionalDefines.SetDefine(TEXT("row_major"), TEXT("")); static FName NAME_SF_METAL(TEXT("SF_METAL")); static FName NAME_SF_METAL_MRT(TEXT("SF_METAL_MRT")); if (Input.ShaderFormat == NAME_SF_METAL) { AdditionalDefines.SetDefine(TEXT("METAL_PROFILE"), 1); } else if (Input.ShaderFormat == NAME_SF_METAL_MRT) { AdditionalDefines.SetDefine(TEXT("METAL_MRT_PROFILE"), 1); } else { Output.bSucceeded = false; new(Output.Errors) FShaderCompilerError(*FString::Printf(TEXT("Invalid shader format '%s' passed to compiler."), *Input.ShaderFormat.ToString())); return; } const bool bDumpDebugInfo = (Input.DumpDebugInfoPath != TEXT("") && IFileManager::Get().DirectoryExists(*Input.DumpDebugInfoPath)); AdditionalDefines.SetDefine(TEXT("COMPILER_SUPPORTS_ATTRIBUTES"), (uint32)1); if (PreprocessShader(PreprocessedShader, Output, Input, AdditionalDefines)) { char* MetalShaderSource = NULL; char* ErrorLog = NULL; const EHlslShaderFrequency FrequencyTable[] = { HSF_VertexShader, HSF_InvalidFrequency, HSF_InvalidFrequency, HSF_PixelShader, HSF_InvalidFrequency, HSF_ComputeShader }; const EHlslShaderFrequency Frequency = FrequencyTable[Input.Target.Frequency]; if (Frequency == HSF_InvalidFrequency) { Output.bSucceeded = false; FShaderCompilerError* NewError = new(Output.Errors) FShaderCompilerError(); NewError->StrippedErrorMessage = FString::Printf( TEXT("%s shaders not supported for use in Metal."), GLFrequencyStringTable[Input.Target.Frequency] ); return; } // This requires removing the HLSLCC_NoPreprocess flag later on! if (!RemoveUniformBuffersFromSource(PreprocessedShader)) { return; } // Write out the preprocessed file and a batch file to compile it if requested (DumpDebugInfoPath is valid) if (bDumpDebugInfo) { FArchive* FileWriter = IFileManager::Get().CreateFileWriter(*(Input.DumpDebugInfoPath / Input.SourceFilename + TEXT(".usf"))); if (FileWriter) { auto AnsiSourceFile = StringCast<ANSICHAR>(*PreprocessedShader); FileWriter->Serialize((ANSICHAR*)AnsiSourceFile.Get(), AnsiSourceFile.Length()); FileWriter->Close(); delete FileWriter; } } uint32 CCFlags = HLSLCC_NoPreprocess | HLSLCC_PackUniforms; //CCFlags |= HLSLCC_FlattenUniformBuffers | HLSLCC_FlattenUniformBufferStructures; if (bDumpDebugInfo) { const FString MetalFile = (Input.DumpDebugInfoPath / TEXT("Output.metal")); const FString USFFile = (Input.DumpDebugInfoPath / Input.SourceFilename) + TEXT(".usf"); const FString CCBatchFileContents = CreateCommandLineHLSLCC(USFFile, MetalFile, *Input.EntryPointName, Frequency, CCFlags); if (!CCBatchFileContents.IsEmpty()) { FFileHelper::SaveStringToFile(CCBatchFileContents, *(Input.DumpDebugInfoPath / TEXT("CrossCompile.bat"))); } } // Required as we added the RemoveUniformBuffersFromSource() function (the cross-compiler won't be able to interpret comments w/o a preprocessor) CCFlags &= ~HLSLCC_NoPreprocess; FMetalCodeBackend MetalBackEnd(CCFlags); FMetalLanguageSpec MetalLanguageSpec; int32 Result = HlslCrossCompile( TCHAR_TO_ANSI(*Input.SourceFilename), TCHAR_TO_ANSI(*PreprocessedShader), TCHAR_TO_ANSI(*Input.EntryPointName), Frequency, &MetalBackEnd, &MetalLanguageSpec, CCFlags, HlslCompilerTarget, &MetalShaderSource, &ErrorLog ); int32 SourceLen = MetalShaderSource ? FCStringAnsi::Strlen(MetalShaderSource) : 0; if (bDumpDebugInfo) { if (SourceLen > 0) { FArchive* FileWriter = IFileManager::Get().CreateFileWriter(*(Input.DumpDebugInfoPath / Input.SourceFilename + TEXT(".metal"))); if (FileWriter) { FileWriter->Serialize(MetalShaderSource, SourceLen + 1); FileWriter->Close(); delete FileWriter; } } } if (Result != 0) { Output.Target = Input.Target; BuildMetalShaderOutput(Output, Input, MetalShaderSource, SourceLen, Output.Errors); } else { FString Tmp = ANSI_TO_TCHAR(ErrorLog); TArray<FString> ErrorLines; Tmp.ParseIntoArray(ErrorLines, TEXT("\n"), true); for (int32 LineIndex = 0; LineIndex < ErrorLines.Num(); ++LineIndex) { const FString& Line = ErrorLines[LineIndex]; ParseHlslccError(Output.Errors, Line); } } if (MetalShaderSource) { free(MetalShaderSource); } if (ErrorLog) { free(ErrorLog); } } }
/** * Construct the final microcode from the compiled and verified shader source. * @param ShaderOutput - Where to store the microcode and parameter map. * @param InShaderSource - Metal source with input/output signature. * @param SourceLen - The length of the Metal source code. */ static void BuildMetalShaderOutput( FShaderCompilerOutput& ShaderOutput, const FShaderCompilerInput& ShaderInput, const ANSICHAR* InShaderSource, int32 SourceLen, TArray<FShaderCompilerError>& OutErrors ) { FMetalCodeHeader Header = {0}; const ANSICHAR* ShaderSource = InShaderSource; FShaderParameterMap& ParameterMap = ShaderOutput.ParameterMap; EShaderFrequency Frequency = (EShaderFrequency)ShaderOutput.Target.Frequency; TBitArray<> UsedUniformBufferSlots; UsedUniformBufferSlots.Init(false,32); // Write out the magic markers. Header.Frequency = Frequency; #define DEF_PREFIX_STR(Str) \ const ANSICHAR* Str##Prefix = "// @" #Str ": "; \ const int32 Str##PrefixLen = FCStringAnsi::Strlen(Str##Prefix) DEF_PREFIX_STR(Inputs); DEF_PREFIX_STR(Outputs); DEF_PREFIX_STR(UniformBlocks); DEF_PREFIX_STR(Uniforms); DEF_PREFIX_STR(PackedGlobals); DEF_PREFIX_STR(PackedUB); DEF_PREFIX_STR(PackedUBCopies); DEF_PREFIX_STR(PackedUBGlobalCopies); DEF_PREFIX_STR(Samplers); DEF_PREFIX_STR(UAVs); DEF_PREFIX_STR(SamplerStates); DEF_PREFIX_STR(NumThreads); #undef DEF_PREFIX_STR // Skip any comments that come before the signature. while ( FCStringAnsi::Strncmp(ShaderSource, "//", 2) == 0 && FCStringAnsi::Strncmp(ShaderSource, "// @", 4) != 0 ) { while (*ShaderSource && *ShaderSource++ != '\n') {} } // HLSLCC first prints the list of inputs. if (FCStringAnsi::Strncmp(ShaderSource, InputsPrefix, InputsPrefixLen) == 0) { ShaderSource += InputsPrefixLen; // Only inputs for vertex shaders must be tracked. if (Frequency == SF_Vertex) { const ANSICHAR* AttributePrefix = "in_ATTRIBUTE"; const int32 AttributePrefixLen = FCStringAnsi::Strlen(AttributePrefix); while (*ShaderSource && *ShaderSource != '\n') { // Skip the type. while (*ShaderSource && *ShaderSource++ != ':') {} // Only process attributes. if (FCStringAnsi::Strncmp(ShaderSource, AttributePrefix, AttributePrefixLen) == 0) { ShaderSource += AttributePrefixLen; uint8 AttributeIndex = ParseNumber(ShaderSource); Header.Bindings.InOutMask |= (1 << AttributeIndex); } // Skip to the next. while (*ShaderSource && *ShaderSource != ',' && *ShaderSource != '\n') { ShaderSource++; } if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } else { // Skip to the next line. while (*ShaderSource && *ShaderSource++ != '\n') {} } } // Then the list of outputs. if (FCStringAnsi::Strncmp(ShaderSource, OutputsPrefix, OutputsPrefixLen) == 0) { ShaderSource += OutputsPrefixLen; // Only outputs for pixel shaders must be tracked. if (Frequency == SF_Pixel) { const ANSICHAR* TargetPrefix = "out_Target"; const int32 TargetPrefixLen = FCStringAnsi::Strlen(TargetPrefix); while (*ShaderSource && *ShaderSource != '\n') { // Skip the type. while (*ShaderSource && *ShaderSource++ != ':') {} // Handle targets. if (FCStringAnsi::Strncmp(ShaderSource, TargetPrefix, TargetPrefixLen) == 0) { ShaderSource += TargetPrefixLen; uint8 TargetIndex = ParseNumber(ShaderSource); Header.Bindings.InOutMask |= (1 << TargetIndex); } // Handle depth writes. else if (FCStringAnsi::Strcmp(ShaderSource, "gl_FragDepth") == 0) { Header.Bindings.InOutMask |= 0x8000; } // Skip to the next. while (*ShaderSource && *ShaderSource != ',' && *ShaderSource != '\n') { ShaderSource++; } if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } else { // Skip to the next line. while (*ShaderSource && *ShaderSource++ != '\n') {} } } bool bHasRegularUniformBuffers = false; // Then 'normal' uniform buffers. if (FCStringAnsi::Strncmp(ShaderSource, UniformBlocksPrefix, UniformBlocksPrefixLen) == 0) { ShaderSource += UniformBlocksPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { FString BufferName = ParseIdentifier(ShaderSource); verify(BufferName.Len() > 0); verify(Match(ShaderSource, '(')); uint16 UBIndex = ParseNumber(ShaderSource); if (UBIndex >= Header.Bindings.NumUniformBuffers) { Header.Bindings.NumUniformBuffers = UBIndex + 1; } UsedUniformBufferSlots[UBIndex] = true; verify(Match(ShaderSource, ')')); ParameterMap.AddParameterAllocation(*BufferName, UBIndex, 0, 0); bHasRegularUniformBuffers = true; // Skip the comma. if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } Match(ShaderSource, '\n'); } // Then uniforms. const uint16 BytesPerComponent = 4; /* uint16 PackedUniformSize[OGL_NUM_PACKED_UNIFORM_ARRAYS] = {0}; FMemory::Memzero(&PackedUniformSize, sizeof(PackedUniformSize)); */ if (FCStringAnsi::Strncmp(ShaderSource, UniformsPrefix, UniformsPrefixLen) == 0) { // @todo-mobile: Will we ever need to support this code path? check(0); /* ShaderSource += UniformsPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { uint16 ArrayIndex = 0; uint16 Offset = 0; uint16 NumComponents = 0; FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); ArrayIndex = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); Offset = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); NumComponents = ParseNumber(ShaderSource); verify(Match(ShaderSource, ')')); ParameterMap.AddParameterAllocation( *ParameterName, ArrayIndex, Offset * BytesPerComponent, NumComponents * BytesPerComponent ); if (ArrayIndex < OGL_NUM_PACKED_UNIFORM_ARRAYS) { PackedUniformSize[ArrayIndex] = FMath::Max<uint16>( PackedUniformSize[ArrayIndex], BytesPerComponent * (Offset + NumComponents) ); } // Skip the comma. if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } Match(ShaderSource, '\n'); */ } // Packed global uniforms TMap<ANSICHAR, uint16> PackedGlobalArraySize; if (FCStringAnsi::Strncmp(ShaderSource, PackedGlobalsPrefix, PackedGlobalsPrefixLen) == 0) { ShaderSource += PackedGlobalsPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { ANSICHAR ArrayIndex = 0; uint16 Offset = 0; uint16 NumComponents = 0; FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); ArrayIndex = *ShaderSource++; verify(Match(ShaderSource, ':')); Offset = ParseNumber(ShaderSource); verify(Match(ShaderSource, ',')); NumComponents = ParseNumber(ShaderSource); verify(Match(ShaderSource, ')')); ParameterMap.AddParameterAllocation( *ParameterName, ArrayIndex, Offset * BytesPerComponent, NumComponents * BytesPerComponent ); uint16& Size = PackedGlobalArraySize.FindOrAdd(ArrayIndex); Size = FMath::Max<uint16>(BytesPerComponent * (Offset + NumComponents), Size); if (Match(ShaderSource, '\n')) { break; } // Skip the comma. verify(Match(ShaderSource, ',')); } Match(ShaderSource, '\n'); } // Packed Uniform Buffers TMap<int, TMap<ANSICHAR, uint16> > PackedUniformBuffersSize; while (FCStringAnsi::Strncmp(ShaderSource, PackedUBPrefix, PackedUBPrefixLen) == 0) { ShaderSource += PackedUBPrefixLen; FString BufferName = ParseIdentifier(ShaderSource); verify(BufferName.Len() > 0); verify(Match(ShaderSource, '(')); uint16 BufferIndex = ParseNumber(ShaderSource); check(BufferIndex == Header.Bindings.NumUniformBuffers); verify(Match(ShaderSource, ')')); ParameterMap.AddParameterAllocation(*BufferName, Header.Bindings.NumUniformBuffers++, 0, 0); verify(Match(ShaderSource, ':')); Match(ShaderSource, ' '); while (*ShaderSource && *ShaderSource != '\n') { FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); ParseNumber(ShaderSource); verify(Match(ShaderSource, ',')); ParseNumber(ShaderSource); verify(Match(ShaderSource, ')')); if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } // Packed Uniform Buffers copy lists & setup sizes for each UB/Precision entry if (FCStringAnsi::Strncmp(ShaderSource, PackedUBCopiesPrefix, PackedUBCopiesPrefixLen) == 0) { ShaderSource += PackedUBCopiesPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { FMetalUniformBufferCopyInfo CopyInfo; CopyInfo.SourceUBIndex = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.SourceOffsetInFloats = ParseNumber(ShaderSource); verify(Match(ShaderSource, '-')); CopyInfo.DestUBIndex = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.DestUBTypeName = *ShaderSource++; CopyInfo.DestUBTypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(CopyInfo.DestUBTypeName); verify(Match(ShaderSource, ':')); CopyInfo.DestOffsetInFloats = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.SizeInFloats = ParseNumber(ShaderSource); Header.UniformBuffersCopyInfo.Add(CopyInfo); auto& UniformBufferSize = PackedUniformBuffersSize.FindOrAdd(CopyInfo.DestUBIndex); uint16& Size = UniformBufferSize.FindOrAdd(CopyInfo.DestUBTypeName); Size = FMath::Max<uint16>(BytesPerComponent * (CopyInfo.DestOffsetInFloats + CopyInfo.SizeInFloats), Size); if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } if (FCStringAnsi::Strncmp(ShaderSource, PackedUBGlobalCopiesPrefix, PackedUBGlobalCopiesPrefixLen) == 0) { ShaderSource += PackedUBGlobalCopiesPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { FMetalUniformBufferCopyInfo CopyInfo; CopyInfo.SourceUBIndex = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.SourceOffsetInFloats = ParseNumber(ShaderSource); verify(Match(ShaderSource, '-')); CopyInfo.DestUBIndex = 0; CopyInfo.DestUBTypeName = *ShaderSource++; CopyInfo.DestUBTypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(CopyInfo.DestUBTypeName); verify(Match(ShaderSource, ':')); CopyInfo.DestOffsetInFloats = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.SizeInFloats = ParseNumber(ShaderSource); Header.UniformBuffersCopyInfo.Add(CopyInfo); uint16& Size = PackedGlobalArraySize.FindOrAdd(CopyInfo.DestUBTypeName); Size = FMath::Max<uint16>(BytesPerComponent * (CopyInfo.DestOffsetInFloats + CopyInfo.SizeInFloats), Size); if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } Header.Bindings.bHasRegularUniformBuffers = bHasRegularUniformBuffers; // Setup Packed Array info Header.Bindings.PackedGlobalArrays.Reserve(PackedGlobalArraySize.Num()); for (auto Iterator = PackedGlobalArraySize.CreateIterator(); Iterator; ++Iterator) { ANSICHAR TypeName = Iterator.Key(); uint16 Size = Iterator.Value(); Size = (Size + 0xf) & (~0xf); CrossCompiler::FPackedArrayInfo Info; Info.Size = Size; Info.TypeName = TypeName; Info.TypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(TypeName); Header.Bindings.PackedGlobalArrays.Add(Info); } // Setup Packed Uniform Buffers info Header.Bindings.PackedUniformBuffers.Reserve(PackedUniformBuffersSize.Num()); for (auto Iterator = PackedUniformBuffersSize.CreateIterator(); Iterator; ++Iterator) { int BufferIndex = Iterator.Key(); auto& ArraySizes = Iterator.Value(); TArray<CrossCompiler::FPackedArrayInfo> InfoArray; InfoArray.Reserve(ArraySizes.Num()); for (auto IterSizes = ArraySizes.CreateIterator(); IterSizes; ++IterSizes) { ANSICHAR TypeName = IterSizes.Key(); uint16 Size = IterSizes.Value(); Size = (Size + 0xf) & (~0xf); CrossCompiler::FPackedArrayInfo Info; Info.Size = Size; Info.TypeName = TypeName; Info.TypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(TypeName); InfoArray.Add(Info); } Header.Bindings.PackedUniformBuffers.Add(InfoArray); } // Then samplers. if (FCStringAnsi::Strncmp(ShaderSource, SamplersPrefix, SamplersPrefixLen) == 0) { ShaderSource += SamplersPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { uint16 Offset = 0; uint16 NumSamplers = 0; FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); Offset = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); NumSamplers = ParseNumber(ShaderSource); ParameterMap.AddParameterAllocation( *ParameterName, 0, Offset, NumSamplers ); Header.Bindings.NumSamplers = FMath::Max<uint8>( Header.Bindings.NumSamplers, Offset + NumSamplers ); if (Match(ShaderSource, '[')) { // Sampler States do { FString SamplerState = ParseIdentifier(ShaderSource); checkSlow(SamplerState.Len() != 0); ParameterMap.AddParameterAllocation( *SamplerState, 0, Offset, NumSamplers ); } while (Match(ShaderSource, ',')); verify(Match(ShaderSource, ']')); } verify(Match(ShaderSource, ')')); if (Match(ShaderSource, '\n')) { break; } // Skip the comma. verify(Match(ShaderSource, ',')); } } // Then UAVs (images in Metal) if (FCStringAnsi::Strncmp(ShaderSource, UAVsPrefix, UAVsPrefixLen) == 0) { ShaderSource += UAVsPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { uint16 Offset = 0; uint16 NumUAVs = 0; FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); Offset = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); NumUAVs = ParseNumber(ShaderSource); ParameterMap.AddParameterAllocation( *ParameterName, 0, Offset, NumUAVs ); Header.Bindings.NumUAVs = FMath::Max<uint8>( Header.Bindings.NumUAVs, Offset + NumUAVs ); verify(Match(ShaderSource, ')')); if (Match(ShaderSource, '\n')) { break; } // Skip the comma. verify(Match(ShaderSource, ',')); } } if (FCStringAnsi::Strncmp(ShaderSource, NumThreadsPrefix, NumThreadsPrefixLen) == 0) { ShaderSource += NumThreadsPrefixLen; Header.NumThreadsX = ParseNumber(ShaderSource); verify(Match(ShaderSource, ',')); Match(ShaderSource, ' '); Header.NumThreadsY = ParseNumber(ShaderSource); verify(Match(ShaderSource, ',')); Match(ShaderSource, ' '); Header.NumThreadsZ = ParseNumber(ShaderSource); verify(Match(ShaderSource, '\n')); } // Build the SRT for this shader. { // Build the generic SRT for this shader. FShaderResourceTable GenericSRT; BuildResourceTableMapping(ShaderInput.Environment.ResourceTableMap, ShaderInput.Environment.ResourceTableLayoutHashes, UsedUniformBufferSlots, ShaderOutput.ParameterMap, GenericSRT); // Copy over the bits indicating which resource tables are active. Header.Bindings.ShaderResourceTable.ResourceTableBits = GenericSRT.ResourceTableBits; Header.Bindings.ShaderResourceTable.ResourceTableLayoutHashes = GenericSRT.ResourceTableLayoutHashes; // Now build our token streams. BuildResourceTableTokenStream(GenericSRT.TextureMap, GenericSRT.MaxBoundResourceTable, Header.Bindings.ShaderResourceTable.TextureMap); BuildResourceTableTokenStream(GenericSRT.ShaderResourceViewMap, GenericSRT.MaxBoundResourceTable, Header.Bindings.ShaderResourceTable.ShaderResourceViewMap); BuildResourceTableTokenStream(GenericSRT.SamplerMap, GenericSRT.MaxBoundResourceTable, Header.Bindings.ShaderResourceTable.SamplerMap); BuildResourceTableTokenStream(GenericSRT.UnorderedAccessViewMap, GenericSRT.MaxBoundResourceTable, Header.Bindings.ShaderResourceTable.UnorderedAccessViewMap); Header.Bindings.NumUniformBuffers = FMath::Max((uint8)GetNumUniformBuffersUsed(GenericSRT), Header.Bindings.NumUniformBuffers); } const int32 MaxSamplers = GetFeatureLevelMaxTextureSamplers(ERHIFeatureLevel::ES3_1); if (Header.Bindings.NumSamplers > MaxSamplers) { ShaderOutput.bSucceeded = false; FShaderCompilerError* NewError = new(ShaderOutput.Errors) FShaderCompilerError(); NewError->StrippedErrorMessage = FString::Printf(TEXT("shader uses %d samplers exceeding the limit of %d"), Header.Bindings.NumSamplers, MaxSamplers); } else { #if METAL_OFFLINE_COMPILE // at this point, the shader source is ready to be compiled FString InputFilename = FPaths::CreateTempFilename(*FPaths::EngineIntermediateDir(), TEXT("ShaderIn"), TEXT("")); FString ObjFilename = InputFilename + TEXT(".o"); FString ArFilename = InputFilename + TEXT(".ar"); FString OutputFilename = InputFilename + TEXT(".lib"); InputFilename = InputFilename + TEXT(".metal"); // write out shader source FFileHelper::SaveStringToFile(FString(ShaderSource), *InputFilename); int32 ReturnCode = 0; FString Results; FString Errors; bool bHadError = true; // metal commandlines FString Params = FString::Printf(TEXT("-std=ios-metal1.0 %s -o %s"), *InputFilename, *ObjFilename); FPlatformProcess::ExecProcess( TEXT("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/bin/metal"), *Params, &ReturnCode, &Results, &Errors ); // handle compile error if (ReturnCode != 0 || IFileManager::Get().FileSize(*ObjFilename) <= 0) { // FShaderCompilerError* Error = new(OutErrors) FShaderCompilerError(); // Error->ErrorFile = InputFilename; // Error->ErrorLineString = TEXT("0"); // Error->StrippedErrorMessage = Results + Errors; } else { Params = FString::Printf(TEXT("r %s %s"), *ArFilename, *ObjFilename); FPlatformProcess::ExecProcess( TEXT("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/bin/metal-ar"), *Params, &ReturnCode, &Results, &Errors ); // handle compile error if (ReturnCode != 0 || IFileManager::Get().FileSize(*ArFilename) <= 0) { // FShaderCompilerError* Error = new(OutErrors) FShaderCompilerError(); // Error->ErrorFile = InputFilename; // Error->ErrorLineString = TEXT("0"); // Error->StrippedErrorMessage = Results + Errors; } else { Params = FString::Printf(TEXT("-o %s %s"), *OutputFilename, *ArFilename); FPlatformProcess::ExecProcess( TEXT("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/bin/metallib"), *Params, &ReturnCode, &Results, &Errors ); // handle compile error if (ReturnCode != 0 || IFileManager::Get().FileSize(*OutputFilename) <= 0) { // FShaderCompilerError* Error = new(OutErrors) FShaderCompilerError(); // Error->ErrorFile = InputFilename; // Error->ErrorLineString = TEXT("0"); // Error->StrippedErrorMessage = Results + Errors; } else { bHadError = false; // Write out the header and compiled shader code FMemoryWriter Ar(ShaderOutput.Code, true); uint8 PrecompiledFlag = 1; Ar << PrecompiledFlag; Ar << Header; // load output TArray<uint8> CompiledShader; FFileHelper::LoadFileToArray(CompiledShader, *OutputFilename); // jam it into the output bytes Ar.Serialize(CompiledShader.GetData(), CompiledShader.Num()); ShaderOutput.NumInstructions = 0; ShaderOutput.NumTextureSamplers = Header.Bindings.NumSamplers; ShaderOutput.bSucceeded = true; } } } if (bHadError) { // Write out the header and shader source code. FMemoryWriter Ar(ShaderOutput.Code, true); uint8 PrecompiledFlag = 0; Ar << PrecompiledFlag; Ar << Header; Ar.Serialize((void*)ShaderSource, SourceLen + 1 - (ShaderSource - InShaderSource)); ShaderOutput.NumInstructions = 0; ShaderOutput.NumTextureSamplers = Header.Bindings.NumSamplers; ShaderOutput.bSucceeded = true; } IFileManager::Get().Delete(*InputFilename); IFileManager::Get().Delete(*ObjFilename); IFileManager::Get().Delete(*ArFilename); IFileManager::Get().Delete(*OutputFilename); #else // Write out the header and shader source code. FMemoryWriter Ar(ShaderOutput.Code, true); uint8 PrecompiledFlag = 0; Ar << PrecompiledFlag; Ar << Header; Ar.Serialize((void*)ShaderSource, SourceLen + 1 - (ShaderSource - InShaderSource)); ShaderOutput.NumInstructions = 0; ShaderOutput.NumTextureSamplers = Header.Bindings.NumSamplers; ShaderOutput.bSucceeded = true; #endif } }
/** * Create a search result from a server response * * @param ServerDetails Steam server details */ void FOnlineAsyncTaskSteamFindServerBase::ParseSearchResult(class gameserveritem_t* ServerDetails) { TSharedRef<FInternetAddr> ServerAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr(); ServerAddr->SetIp(ServerDetails->m_NetAdr.GetIP()); ServerAddr->SetPort(ServerDetails->m_NetAdr.GetConnectionPort()); int32 ServerQueryPort = ServerDetails->m_NetAdr.GetQueryPort(); UE_LOG_ONLINE(Warning, TEXT("Server response IP:%s"), *ServerAddr->ToString(false)); if (ServerDetails->m_bHadSuccessfulResponse) { FString GameTags(UTF8_TO_TCHAR(ServerDetails->m_szGameTags)); // Check for build compatibility int32 ServerBuildId = 0; int32 BuildUniqueId = GetBuildUniqueId(); TArray<FString> TagArray; GameTags.ParseIntoArray(TagArray, TEXT(","), true); if (TagArray.Num() > 0 && TagArray[0].StartsWith(STEAMKEY_BUILDUNIQUEID)) { ServerBuildId = FCString::Atoi(*TagArray[0].Mid(ARRAY_COUNT(STEAMKEY_BUILDUNIQUEID))); } if (ServerBuildId != 0 && ServerBuildId == BuildUniqueId) { // Create a new pending search result FPendingSearchResultSteam* NewPendingSearch = new (PendingSearchResults) FPendingSearchResultSteam(this); NewPendingSearch->ServerId = FUniqueNetIdSteam(ServerDetails->m_steamID); NewPendingSearch->HostAddr = ServerAddr; // Fill search result members FOnlineSessionSearchResult* NewSearchResult = &NewPendingSearch->PendingSearchResult; NewSearchResult->PingInMs = FMath::Clamp(ServerDetails->m_nPing, 0, MAX_QUERY_PING); // Fill session members FOnlineSession* NewSession = &NewSearchResult->Session; //NewSession->OwningUserId = ; NewSession->OwningUserName = UTF8_TO_TCHAR(ServerDetails->GetName()); NewSession->NumOpenPublicConnections = ServerDetails->m_nMaxPlayers - ServerDetails->m_nPlayers; NewSession->NumOpenPrivateConnections = 0; // Fill session settings members NewSession->SessionSettings.NumPublicConnections = ServerDetails->m_nMaxPlayers; NewSession->SessionSettings.NumPrivateConnections = 0; NewSession->SessionSettings.bAntiCheatProtected = ServerDetails->m_bSecure ? true : false; NewSession->SessionSettings.Set(SETTING_MAPNAME, FString(UTF8_TO_TCHAR(ServerDetails->m_szMap)), EOnlineDataAdvertisementType::ViaOnlineService); // Start a rules request for this new result NewPendingSearch->ServerQueryHandle = SteamMatchmakingServersPtr->ServerRules(ServerDetails->m_NetAdr.GetIP(), ServerQueryPort, NewPendingSearch); if (NewPendingSearch->ServerQueryHandle == HSERVERQUERY_INVALID) { // Remove the failed element PendingSearchResults.RemoveAtSwap(PendingSearchResults.Num() - 1); } } else { UE_LOG_ONLINE(Warning, TEXT("Removed incompatible build: ServerBuildUniqueId = 0x%08x, GetBuildUniqueId() = 0x%08x"), ServerBuildId, BuildUniqueId); } } }
bool UWorld::ComponentSweepMulti(TArray<struct FHitResult>& OutHits, class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FRotator& Rot, const struct FComponentQueryParams& Params) const { if(GetPhysicsScene() == NULL) { return false; } if(PrimComp == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : No PrimComp")); return false; } // if target is skeletalmeshcomponent and do not support singlebody physics if ( !PrimComp->ShouldTrackOverlaps() ) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName()); return false; } ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType(); #if WITH_PHYSX // if extent is 0, do line trace if (PrimComp->IsZeroExtent()) { return RaycastMulti(this, OutHits, Start, End, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())); } PxRigidActor* PRigidActor = PrimComp->BodyInstance.GetPxRigidActor(); if(PRigidActor == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) No physics data"), *PrimComp->GetPathName()); return false; } PxScene * const PScene = PRigidActor->getScene(); OutHits.Empty(); // Get all the shapes from the actor TArray<PxShape*, TInlineAllocator<8>> PShapes; { SCOPED_SCENE_READ_LOCK(PScene); PShapes.AddZeroed(PRigidActor->getNbShapes()); PRigidActor->getShapes(PShapes.GetData(), PShapes.Num()); } // calculate the test global pose of the actor PxTransform PGlobalStartPose = U2PTransform(FTransform(Start)); PxTransform PGlobalEndPose = U2PTransform(FTransform(End)); bool bHaveBlockingHit = false; PxQuat PGeomRot = U2PQuat(Rot.Quaternion()); // Iterate over each shape SCENE_LOCK_READ(PScene); for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++) { PxShape* PShape = PShapes[ShapeIdx]; check(PShape); TArray<struct FHitResult> Hits; // Calc shape global pose PxTransform PLocalShape = PShape->getLocalPose(); PxTransform PShapeGlobalStartPose = PGlobalStartPose.transform(PLocalShape); PxTransform PShapeGlobalEndPose = PGlobalEndPose.transform(PLocalShape); // consider localshape rotation for shape rotation PxQuat PShapeRot = PGeomRot * PLocalShape.q; GET_GEOMETRY_FROM_SHAPE(PGeom, PShape); if(PGeom != NULL) { SCENE_UNLOCK_READ(PScene); if (GeomSweepMulti(this, *PGeom, PShapeRot, Hits, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()))) { bHaveBlockingHit = true; } OutHits.Append(Hits); SCENE_LOCK_READ(PScene); } } SCENE_UNLOCK_READ(PScene); return bHaveBlockingHit; #endif //WITH_PHYSX return false; }
FVector AvoidCones(TArray<FVelocityAvoidanceCone>& AllCones, const FVector& BasePosition, const FVector& DesiredPosition, const int NumConesToTest) { FVector CurrentPosition = DesiredPosition; float DistanceInsidePlane_Current[2]; float DistanceInsidePlane_Base[2]; float Weighting[2]; int ConePlaneIndex; //AllCones is non-const so that it can be reordered, but nothing should be added or removed from it. checkSlow(NumConesToTest <= AllCones.Num()); TArray<FVelocityAvoidanceCone>::TIterator It = AllCones.CreateIterator(); for (int i = 0; i < NumConesToTest; ++i, ++It) { FVelocityAvoidanceCone& CurrentCone = *It; //See if CurrentPosition is outside this cone. If it is, then this cone doesn't obstruct us. DistanceInsidePlane_Current[0] = (CurrentPosition|CurrentCone.ConePlane[0]) - CurrentCone.ConePlane[0].W; DistanceInsidePlane_Current[1] = (CurrentPosition|CurrentCone.ConePlane[1]) - CurrentCone.ConePlane[1].W; if ((DistanceInsidePlane_Current[0] <= 0.0f) || (DistanceInsidePlane_Current[1] <= 0.0f)) { //We're not inside this cone, continue past it. //If we wanted to, we could check if CurrentPosition and BasePosition are on the same side of the cone, in which case the cone can be removed from this segment test entirely. continue; } //If we've gotten here, CurrentPosition is inside the cone. If BasePosition is also inside the cone, this entire segment is blocked. DistanceInsidePlane_Base[0] = (BasePosition|CurrentCone.ConePlane[0]) - CurrentCone.ConePlane[0].W; DistanceInsidePlane_Base[1] = (BasePosition|CurrentCone.ConePlane[1]) - CurrentCone.ConePlane[1].W; //We know that the BasePosition isn't in the cone, but CurrentPosition is. We should find the point where the line segment between CurrentPosition and BasePosition exits the cone. #define CALCULATE_WEIGHTING(index) Weighting[index] = -DistanceInsidePlane_Base[index] / (DistanceInsidePlane_Current[index] - DistanceInsidePlane_Base[index]); if (DistanceInsidePlane_Base[0] <= 0.0f) { CALCULATE_WEIGHTING(0); if (DistanceInsidePlane_Base[1] <= 0.0f) { CALCULATE_WEIGHTING(1); ConePlaneIndex = (Weighting[1] > Weighting[0]) ? 1 : 0; } else { ConePlaneIndex = 0; } } else if (DistanceInsidePlane_Base[1] <= 0.0f) { CALCULATE_WEIGHTING(1); ConePlaneIndex = 1; } else { //BasePosition is also in the cone. This entire line segment of movement is invalidated. I'm considering a way to return false/NULL here. return BasePosition; } //Weighted average of points based on planar distance gives us the answer we want without needing to make a direction vector. CurrentPosition = (CurrentPosition * Weighting[ConePlaneIndex]) + (BasePosition * (1.0f - Weighting[ConePlaneIndex])); #undef CALCULATE_WEIGHTING //This cone doesn't need to be used again, so drop it from the list (by shuffling it to the end and decrementing the cone count). //This probably ruins our iterator, but it doesn't matter because we're done. AllCones.Swap(i, NumConesToTest - 1); //Don't care if this is swapping an element with itself; the swap function checks this already. return AvoidCones(AllCones, BasePosition, CurrentPosition, NumConesToTest - 1); } return CurrentPosition; }
void UEnvQueryGenerator_Donut::GenerateItems(FEnvQueryInstance& QueryInstance) const { TArray<FVector> CenterPoints; QueryInstance.PrepareContext(Center, CenterPoints); if (CenterPoints.Num() <= 0) { return; } UObject* BindOwner = QueryInstance.Owner.Get(); InnerRadius.BindData(BindOwner, QueryInstance.QueryID); OuterRadius.BindData(BindOwner, QueryInstance.QueryID); NumberOfRings.BindData(BindOwner, QueryInstance.QueryID); PointsPerRing.BindData(BindOwner, QueryInstance.QueryID); ArcAngle.BindData(BindOwner, QueryInstance.QueryID); float ArcAngleValue = ArcAngle.GetValue(); float InnerRadiusValue = InnerRadius.GetValue(); float OuterRadiusValue = OuterRadius.GetValue(); int32 NumRings = NumberOfRings.GetValue(); int32 NumPoints = PointsPerRing.GetValue(); if ((InnerRadiusValue <= 0.f) || (OuterRadiusValue <= 0.f) || (InnerRadiusValue > OuterRadiusValue) || (NumRings < 1) || (NumPoints < 1)) { return; } const float ArcBisectDeg = GetArcBisectorAngle(QueryInstance); const float ArcAngleDeg = FMath::Clamp(ArcAngleValue, 0.0f, 360.0f); const float RadiusDelta = (OuterRadiusValue - InnerRadiusValue) / (NumRings - 1); const float AngleDelta = 2.0 * PI / NumPoints; float SectionAngle = FMath::DegreesToRadians(ArcBisectDeg); TArray<FNavLocation> Points; Points.Reserve(NumPoints * NumRings); for (int32 SectionIdx = 0; SectionIdx < NumPoints; SectionIdx++, SectionAngle += AngleDelta) { if (IsAngleAllowed(SectionAngle, ArcBisectDeg, ArcAngleDeg, bDefineArc)) { const float SinValue = FMath::Sin(SectionAngle); const float CosValue = FMath::Cos(SectionAngle); float RingRadius = InnerRadiusValue; for (int32 RingIdx = 0; RingIdx < NumRings; RingIdx++, RingRadius += RadiusDelta) { const FVector RingPos(RingRadius * CosValue, RingRadius * SinValue, 0.0f); for (int32 ContextIdx = 0; ContextIdx < CenterPoints.Num(); ContextIdx++) { const FNavLocation PointPos = FNavLocation(CenterPoints[ContextIdx] + RingPos); Points.Add(PointPos); } } } } ProjectAndFilterNavPoints(Points, QueryInstance); StoreNavPoints(Points, QueryInstance); }
// This static function handles all callbacks coming in and when context is services via libwebsocket_service // return value of -1, closes the connection. int FNetworkFileServerHttp::CallBack_HTTP( struct libwebsocket_context *Context, struct libwebsocket *Wsi, enum libwebsocket_callback_reasons Reason, void *User, void *In, size_t Len) { PerSessionData* BufferInfo = (PerSessionData*)User; FNetworkFileServerHttp* Server = (FNetworkFileServerHttp*)libwebsocket_context_user(Context); switch (Reason) { case LWS_CALLBACK_HTTP: // hang on to socket even if there's no data for atleast 60 secs. libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 60); /* if it was not legal POST URL, let it continue and accept data */ if (!lws_hdr_total_length(Wsi, WSI_TOKEN_POST_URI)) { char *requested_uri = (char *) In; // client request the base page. e.g http://unrealfileserver:port/ // just return a banner, probably add some more information, e,g Version, Config, Game. etc. if ( FCString::Strcmp(ANSI_TO_TCHAR(requested_uri), TEXT("/")) == 0 ) { TCHAR Buffer[1024]; TCHAR ServerBanner[] = TEXT("<HTML>This is Unreal File Server</HTML>"); int x = FCString::Sprintf( Buffer, TEXT("HTTP/1.0 200 OK\x0d\x0a") TEXT("Server: Unreal File Server\x0d\x0a") TEXT("Connection: close\x0d\x0a") TEXT("Content-Type: text/html; charset=utf-8\x0d\x0a") TEXT("Content-Length: %u\x0d\x0a\x0d\x0a%s"), FCString::Strlen(ServerBanner), ServerBanner ); // very small data being sent, its fine to just send. libwebsocket_write(Wsi,(unsigned char*)TCHAR_TO_ANSI(Buffer),FCStringAnsi::Strlen(TCHAR_TO_ANSI(Buffer)), LWS_WRITE_HTTP); } else { // client has asked for a file. ( only html/js files are served.) // what type is being served. FString FilePath = FPaths::GameDir() / TEXT("Binaries/HTML5") + FString((ANSICHAR*)In); TCHAR *Mime = NULL; if ( FilePath.Contains(".js")) { Mime = TEXT("application/javascript;charset=UTF-8"); } else { Mime = TEXT("text/html;charset=UTF-8"); } UE_LOG(LogFileServer, Warning, TEXT("HTTP Serving file %s with mime %s "), *FilePath, (Mime)); FString AbsoluteFilePath = FPaths::ConvertRelativePathToFull(FilePath); AbsoluteFilePath.ReplaceInline(TEXT("/"),TEXT("\\")); // we are going to read the complete file in memory and then serve it in batches. // rather than reading and sending in batches because Unreal NFS servers are not running in memory // constrained env and the added complexity is not worth it. TArray<uint8> FileData; FFileHelper::LoadFileToArray(FileData, *AbsoluteFilePath, FILEREAD_Silent); if (FileData.Num() == 0) { // umm. we didn't find file, we should tell the client that we couldn't find it. // send 404. char Header[]= "HTTP/1.1 404 Not Found\x0d\x0a" "Server: Unreal File Server\x0d\x0a" "Connection: close\x0d\x0a"; libwebsocket_write(Wsi,(unsigned char*)Header,FCStringAnsi::Strlen(Header), LWS_WRITE_HTTP); // chug along, client will close the connection. break; } // file up the header. TCHAR Header[1024]; int Length = FCString::Sprintf(Header, TEXT("HTTP/1.1 200 OK\x0d\x0a") TEXT("Server: Unreal File Server\x0d\x0a") TEXT("Connection: close\x0d\x0a") TEXT("Content-Type: %s \x0d\x0a") TEXT("Content-Length: %u\x0d\x0a\x0d\x0a"), Mime,FileData.Num()); // make space for the whole file in our out buffer. BufferInfo->Out.Append((uint8*)TCHAR_TO_ANSI(Header),Length); BufferInfo->Out.Append(FileData); // we need to write back to the client, queue up a write callback. libwebsocket_callback_on_writable(Context, Wsi); } } else { // we got a post request!, queue up a write callback. libwebsocket_callback_on_writable(Context, Wsi); } break; case LWS_CALLBACK_HTTP_BODY: { // post data is coming in, push it on to our incoming buffer. UE_LOG(LogFileServer, Log, TEXT("Incoming HTTP Partial Body Size %d, total size %d"),Len, Len+ BufferInfo->In.Num()); BufferInfo->In.Append((uint8*)In,Len); // we received some data - update time out. libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 60); } break; case LWS_CALLBACK_HTTP_BODY_COMPLETION: { // we have all the post data from the client. // create archives and process them. UE_LOG(LogFileServer, Log, TEXT("Incoming HTTP total size %d"), BufferInfo->In.Num()); FMemoryReader Reader(BufferInfo->In); TArray<uint8> Writer; FNetworkFileServerHttp::Process(Reader,Writer,Server); // even if we have 0 data to push, tell the client that we don't any data. ANSICHAR Header[1024]; int Length = FCStringAnsi::Sprintf( (ANSICHAR*)Header, "HTTP/1.1 200 OK\x0d\x0a" "Server: Unreal File Server\x0d\x0a" "Connection: close\x0d\x0a" "Content-Type: application/octet-stream \x0d\x0a" "Content-Length: %u\x0d\x0a\x0d\x0a", Writer.Num() ); // Add Http Header BufferInfo->Out.Append((uint8*)Header,Length); // Add Binary Data. BufferInfo->Out.Append(Writer); // we have enqueued data increase timeout and push a writable callback. libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 60); libwebsocket_callback_on_writable(Context, Wsi); } break; case LWS_CALLBACK_CLOSED_HTTP: // client went away or //clean up. BufferInfo->In.Empty(); BufferInfo->Out.Empty(); break; case LWS_CALLBACK_PROTOCOL_DESTROY: // we are going away. break; case LWS_CALLBACK_HTTP_WRITEABLE: // get rid of superfluous write callbacks. if ( BufferInfo == NULL ) break; // we have data o send out. if (BufferInfo->Out.Num()) { int SentSize = libwebsocket_write(Wsi,(unsigned char*)BufferInfo->Out.GetData(),BufferInfo->Out.Num(), LWS_WRITE_HTTP); // get rid of the data that has been sent. BufferInfo->Out.RemoveAt(0,SentSize); } break; default: break; } return 0; }
int32 FUniformMeshConverter::Convert( FRHICommandListImmediate& RHICmdList, FSceneRenderer& Renderer, FViewInfo& View, const FPrimitiveSceneInfo* PrimitiveSceneInfo, int32 LODIndex, FUniformMeshBuffers*& OutUniformMeshBuffers, const FMaterialRenderProxy*& OutMaterialRenderProxy, FUniformBufferRHIParamRef& OutPrimitiveUniformBuffer) { const FPrimitiveSceneProxy* PrimitiveSceneProxy = PrimitiveSceneInfo->Proxy; const auto FeatureLevel = View.GetFeatureLevel(); TArray<FMeshBatch> MeshElements; PrimitiveSceneInfo->Proxy->GetMeshDescription(LODIndex, MeshElements); int32 NumTriangles = 0; for (int32 MeshIndex = 0; MeshIndex < MeshElements.Num(); MeshIndex++) { if (ShouldConvertMesh(MeshElements[MeshIndex])) { NumTriangles += MeshElements[MeshIndex].GetNumPrimitives(); } } if (NumTriangles > 0) { if (GUniformMeshTemporaryBuffers.MaxElements < NumTriangles * 3) { GUniformMeshTemporaryBuffers.MaxElements = NumTriangles * 3; GUniformMeshTemporaryBuffers.Release(); GUniformMeshTemporaryBuffers.Initialize(); } RHICmdList.SetRenderTargets(0, (const FRHIRenderTargetView*)NULL, NULL, 0, (const FUnorderedAccessViewRHIParamRef*)NULL); uint32 Offsets[1] = {0}; const FVertexBufferRHIParamRef StreamOutTargets[1] = {GUniformMeshTemporaryBuffers.TriangleData.GetReference()}; RHICmdList.SetStreamOutTargets(1, StreamOutTargets, Offsets); for (int32 MeshIndex = 0; MeshIndex < MeshElements.Num(); MeshIndex++) { const FMeshBatch& Mesh = MeshElements[MeshIndex]; if (ShouldConvertMesh(Mesh)) { FConvertToUniformMeshDrawingPolicy DrawingPolicy( Mesh.VertexFactory, Mesh.MaterialRenderProxy, *Mesh.MaterialRenderProxy->GetMaterial(FeatureLevel), FeatureLevel); //@todo - fix OutMaterialRenderProxy = Mesh.MaterialRenderProxy; RHICmdList.BuildAndSetLocalBoundShaderState(DrawingPolicy.GetBoundShaderStateInput(FeatureLevel)); DrawingPolicy.SetSharedState(RHICmdList, &View, FConvertToUniformMeshDrawingPolicy::ContextDataType()); for (int32 BatchElementIndex = 0; BatchElementIndex < Mesh.Elements.Num(); BatchElementIndex++) { //@todo - fix OutPrimitiveUniformBuffer = IsValidRef(Mesh.Elements[BatchElementIndex].PrimitiveUniformBuffer) ? Mesh.Elements[BatchElementIndex].PrimitiveUniformBuffer : *Mesh.Elements[BatchElementIndex].PrimitiveUniformBufferResource; DrawingPolicy.SetMeshRenderState(RHICmdList, View,PrimitiveSceneProxy,Mesh,BatchElementIndex,false,FMeshDrawingRenderState(),FConvertToUniformMeshDrawingPolicy::ElementDataType(), FConvertToUniformMeshDrawingPolicy::ContextDataType()); DrawingPolicy.DrawMesh(RHICmdList, Mesh, BatchElementIndex); } } } RHICmdList.SetStreamOutTargets(1, (const FVertexBufferRHIParamRef*)NULL, Offsets); } OutUniformMeshBuffers = &GUniformMeshTemporaryBuffers; return NumTriangles; }
void UTexture::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) { Super::PostEditChangeProperty(PropertyChangedEvent); SetLightingGuid(); // Determine whether any property that requires recompression of the texture, or notification to Materials has changed. bool RequiresNotifyMaterials = false; bool DeferCompressionWasEnabled = false; UProperty* PropertyThatChanged = PropertyChangedEvent.Property; if( PropertyThatChanged ) { static const FName CompressionSettingsName("CompressionSettings"); static const FName LODGroupName("LODGroup"); static const FName DeferCompressionName("DeferCompression"); #if WITH_EDITORONLY_DATA static const FName MaxTextureSizeName("MaxTextureSize"); #endif // #if WITH_EDITORONLY_DATA const FName PropertyName = PropertyThatChanged->GetFName(); if (PropertyName == CompressionSettingsName || PropertyName == LODGroupName) { RequiresNotifyMaterials = true; } else if (PropertyName == DeferCompressionName) { DeferCompressionWasEnabled = DeferCompression; } #if WITH_EDITORONLY_DATA else if (PropertyName == MaxTextureSizeName) { if (MaxTextureSize <= 0) { MaxTextureSize = 0; } else { MaxTextureSize = FMath::Min<int32>(FMath::RoundUpToPowerOfTwo(MaxTextureSize), GetMaximumDimension()); } } #endif // #if WITH_EDITORONLY_DATA bool bPreventSRGB = (CompressionSettings == TC_Alpha || CompressionSettings == TC_Normalmap || CompressionSettings == TC_Masks || CompressionSettings == TC_HDR || CompressionSettings == TC_HDR_Compressed); if(bPreventSRGB && SRGB == true) { SRGB = false; } } else { FMaterialUpdateContext UpdateContext; // Update any material that uses this texture TSet<UMaterial*> BaseMaterialsThatUseThisTexture; for (TObjectIterator<UMaterialInterface> It; It; ++It) { UMaterialInterface* MaterialInterface = *It; if (DoesMaterialUseTexture(MaterialInterface, this)) { UMaterial *Material = MaterialInterface->GetMaterial(); bool MaterialAlreadyCompute = false; BaseMaterialsThatUseThisTexture.Add(Material, &MaterialAlreadyCompute); if (!MaterialAlreadyCompute) { UpdateContext.AddMaterial(Material); if (Material->IsTextureForceRecompileCacheRessource(this)) { Material->UpdateMaterialShaderCacheAndTextureReferences(); } } } } //If the DDC key was different the material is already recompile here RequiresNotifyMaterials = false; } NumCinematicMipLevels = FMath::Max<int32>( NumCinematicMipLevels, 0 ); // Don't update the texture resource if we've turned "DeferCompression" on, as this // would cause it to immediately update as an uncompressed texture if( !DeferCompressionWasEnabled && (PropertyChangedEvent.ChangeType & EPropertyChangeType::Interactive) == 0 ) { // Update the texture resource. This will recache derived data if necessary // which may involve recompressing the texture. UpdateResource(); } // Notify any loaded material instances if changed our compression format if (RequiresNotifyMaterials) { TArray<UMaterialInterface*> MaterialsThatUseThisTexture; // Create a material update context to safely update materials. { FMaterialUpdateContext UpdateContext; // Notify any material that uses this texture TSet<UMaterial*> BaseMaterialsThatUseThisTexture; for (TObjectIterator<UMaterialInterface> It; It; ++It) { UMaterialInterface* MaterialInterface = *It; if (DoesMaterialUseTexture(MaterialInterface,this)) { MaterialsThatUseThisTexture.Add(MaterialInterface); // This is a bit tricky. We want to make sure all materials using this texture are // updated. Materials are always updated. Material instances may also have to be // updated and if they have static permutations their children must be updated // whether they use the texture or not! The safe thing to do is to add the instance's // base material to the update context causing all materials in the tree to update. BaseMaterialsThatUseThisTexture.Add(MaterialInterface->GetMaterial()); } } // Go ahead and update any base materials that need to be. for (TSet<UMaterial*>::TConstIterator It(BaseMaterialsThatUseThisTexture); It; ++It) { UpdateContext.AddMaterial(*It); (*It)->PostEditChange(); } } // Now that all materials and instances have updated send necessary callbacks. for (int32 i = 0; i < MaterialsThatUseThisTexture.Num(); ++i) { FEditorSupportDelegates::MaterialTextureSettingsChanged.Broadcast(MaterialsThatUseThisTexture[i]); } } #if WITH_EDITORONLY_DATA // any texture that is referencing this texture as AssociatedNormalMap needs to be informed { TArray<UTexture*> TexturesThatUseThisTexture; for (TObjectIterator<UTexture> It; It; ++It) { UTexture* Tex = *It; if(Tex != this && Tex->CompositeTexture == this && Tex->CompositeTextureMode != CTM_Disabled) { TexturesThatUseThisTexture.Add(Tex); } } for (int32 i = 0; i < TexturesThatUseThisTexture.Num(); ++i) { TexturesThatUseThisTexture[i]->PostEditChange(); } } #endif }
/** Add an item to the output objects array */ void AddItem(UStaticMeshComponent* InComponent, AActor* InActor, TArray< TWeakObjectPtr<UObject> >& OutObjects) { int32 TextureLightMapMemoryUsage; int32 TextureShadowMapMemoryUsage; int32 VertexLightMapMemoryUsage; int32 VertexShadowMapMemoryUsage; int32 StaticLightingResolution; bool bTextureMapping; bool bHasLightmapTexCoords; if(InComponent != NULL && InComponent->GetEstimatedLightAndShadowMapMemoryUsage( TextureLightMapMemoryUsage, TextureShadowMapMemoryUsage, VertexLightMapMemoryUsage, VertexShadowMapMemoryUsage, StaticLightingResolution, bTextureMapping, bHasLightmapTexCoords) ) { UStaticMeshLightingInfo* Entry = ConstructObject<UStaticMeshLightingInfo>(UStaticMeshLightingInfo::StaticClass()); Entry->AddToRoot(); OutObjects.Add(Entry); Entry->StaticMeshActor = InActor; Entry->StaticMeshComponent = InComponent; Entry->StaticMesh = InComponent != NULL ? InComponent->StaticMesh : NULL; Entry->TextureLightMapMemoryUsage = (float)TextureLightMapMemoryUsage / 1024.0f; Entry->TextureShadowMapMemoryUsage = (float)TextureShadowMapMemoryUsage / 1024.0f; Entry->VertexLightMapMemoryUsage = (float)VertexLightMapMemoryUsage / 1024.0f; Entry->VertexShadowMapMemoryUsage = (float)VertexShadowMapMemoryUsage / 1024.0f; Entry->StaticLightingResolution = StaticLightingResolution; Entry->bTextureMapping = bTextureMapping; Entry->bHasLightmapTexCoords = bHasLightmapTexCoords; Entry->UpdateNames(); // Find the lights relevant to the primitive. TArray<ULightComponent*> LightMapRelevantLights; TArray<ULightComponent*> ShadowMapRelevantLights; for (int32 LightIndex = 0; LightIndex < AllLights.Num(); LightIndex++) { ULightComponent* Light = AllLights[LightIndex]; // Only add enabled lights if (Light->bVisible && Light->AffectsPrimitive(InComponent)) { // Check whether the light should use a light-map or shadow-map. const bool bHasStaticLighting = Light->HasStaticLighting(); if (bHasStaticLighting) { LightMapRelevantLights.Add(Light); } // only allow for shadow maps if shadow casting is enabled else if (Light->CastShadows && Light->CastStaticShadows) { ShadowMapRelevantLights.Add(Light); } } } Entry->LightMapLightCount = LightMapRelevantLights.Num(); Entry->ShadowMapLightCount = ShadowMapRelevantLights.Num(); } }
void UEnvQueryManager::Tick(float DeltaTime) { SCOPE_CYCLE_COUNTER(STAT_AI_EQS_Tick); SET_DWORD_STAT(STAT_AI_EQS_NumInstances, RunningQueries.Num()); // @TODO: threads? const double ExecutionTimeWarningSeconds = 0.25; const double MaxAllowedSeconds = 0.010; double TimeLeft = MaxAllowedSeconds; int32 FinishedQueriesCount = 0; TArray<TSharedPtr<FEnvQueryInstance> > RunningQueriesCopy = RunningQueries; { SCOPE_CYCLE_COUNTER(STAT_AI_EQS_TickWork); while (TimeLeft > 0.0 && RunningQueriesCopy.Num() > 0) { bool LoggedExecutionTimeWarning = false; for (int32 Index = 0; Index < RunningQueriesCopy.Num() && TimeLeft > 0.0; Index++) { const double StartTime = FPlatformTime::Seconds(); TSharedPtr<FEnvQueryInstance>& QueryInstance = RunningQueriesCopy[Index]; QueryInstance->ExecuteOneStep(TimeLeft); if (QueryInstance->IsFinished()) { // Always log that we executed total execution time at the end of the query. if (QueryInstance->GetTotalExecutionTime() > ExecutionTimeWarningSeconds) { UE_LOG(LogEQS, Warning, TEXT("Finished query %s over execution time warning. %s"), *QueryInstance->QueryName, *QueryInstance->GetExecutionTimeDescription()); } RunningQueriesCopy.RemoveAt(Index, 1, /*bAllowShrinking=*/false); Index--; ++FinishedQueriesCount; LoggedExecutionTimeWarning = false; } if (!QueryInstance->HasLoggedTimeLimitWarning() && (QueryInstance->GetTotalExecutionTime() > ExecutionTimeWarningSeconds)) { UE_LOG(LogEQS, Warning, TEXT("Query %s over execution time warning. %s"), *QueryInstance->QueryName, *QueryInstance->GetExecutionTimeDescription()); QueryInstance->SetHasLoggedTimeLimitWarning(); } TimeLeft -= (FPlatformTime::Seconds() - StartTime); } } } { SCOPE_CYCLE_COUNTER(STAT_AI_EQS_TickNotifies); for (int32 Index = RunningQueries.Num() - 1; Index >= 0 && FinishedQueriesCount > 0; --Index) { TSharedPtr<FEnvQueryInstance>& QueryInstance = RunningQueries[Index]; if (QueryInstance->IsFinished()) { UE_VLOG_EQS(*QueryInstance.Get(), LogEQS, All); #if USE_EQS_DEBUGGER EQSDebugger.StoreQuery(GetWorld(), QueryInstance); #endif // USE_EQS_DEBUGGER QueryInstance->FinishDelegate.ExecuteIfBound(QueryInstance); RunningQueries.RemoveAtSwap(Index, 1, /*bAllowShrinking=*/false); --FinishedQueriesCount; } } } }
void UConsole::PostRender_InputLine(UCanvas* Canvas, FIntPoint UserInputLinePos) { float xl, yl; // use the smallest font UFont* Font = GEngine->GetSmallFont(); // determine the position for the cursor FString OutStr = FString::Printf(TEXT("%s%s"), *ConsoleDefs::LeadingInputText, *TypedStr); Canvas->StrLen(Font, OutStr,xl,yl); float ClipX = Canvas->ClipX; float ClipY = Canvas->ClipY; if (GEngine->IsConsoleBuild()) { ClipX -= 64; ClipY -= 32; } if (GEngine->IsStereoscopic3D()) { ClipX -= 150; ClipY = ClipY * 0.60; } // Background FCanvasTileItem ConsoleTile( FVector2D( UserInputLinePos.X,UserInputLinePos.Y-6-yl ), DefaultTexture_Black->Resource, FVector2D( ClipX, yl+6 ), FVector2D( 0.0f, 0.0f), FVector2D( 1.0f, 1.0f ), FLinearColor::White ); Canvas->DrawItem( ConsoleTile ); // Separator line ConsoleTile.SetColor( ConsoleDefs::BorderColor ); ConsoleTile.Texture = DefaultTexture_White->Resource; ConsoleTile.Size = FVector2D( ClipX, 2.0f ); Canvas->DrawItem( ConsoleTile ); // Currently typed string FText Str = FText::FromString( OutStr ); FCanvasTextItem ConsoleText( FVector2D( UserInputLinePos.X,UserInputLinePos.Y-3-yl ), Str , GEngine->GetSmallFont(), ConsoleDefs::InputTextColor ); Canvas->DrawItem( ConsoleText ); // draw the remaining text for matching auto-complete if (AutoComplete.Num() > 0) { int32 StartIdx = AutoCompleteIndex; if (StartIdx < 0) { StartIdx = FMath::Max(0, AutoComplete.Num() + StartIdx); } Canvas->StrLen(Font, *ConsoleDefs::LeadingInputText, xl, yl); float y = UserInputLinePos.Y - 6.0f - (yl * 2.0f); // Set the background color/texture of the auto-complete section ConsoleTile.SetColor( ConsoleDefs::AutocompleteBackgroundColor ); ConsoleTile.Texture = DefaultTexture_White->Resource; // wasteful memory allocations but when typing in a console command this is fine TArray<FString> AutoCompleteElements; // to avoid memory many allocations AutoCompleteElements.Empty(MAX_AUTOCOMPLETION_LINES + 1); for (int32 MatchIdx = 0; MatchIdx < MAX_AUTOCOMPLETION_LINES && MatchIdx < AutoComplete.Num(); MatchIdx++) { const FAutoCompleteCommand &Cmd = AutoComplete[StartIdx + MatchIdx]; OutStr = Cmd.Desc; if(OutStr.IsEmpty()) { // no Description means we display the Command directly, without that the line would be empty (happens for ConsoleVariables and some ConsoleSettings->ManualAutoCompleteList) OutStr = Cmd.Command; } AutoCompleteElements.Add(OutStr); } // Display a message if there were more matches if (AutoComplete.Num() >= MAX_AUTOCOMPLETION_LINES) { OutStr = FString::Printf(TEXT("[%i more matches]"), (AutoComplete.Num() - MAX_AUTOCOMPLETION_LINES + 1)); AutoCompleteElements.Add(OutStr); } // background rectangle behind auto completion { float MaxWidth = 0; float MaxHeight = 0; for(int32 i = 0, Num = AutoCompleteElements.Num(); i < Num; ++i) { const FString& AutoCompleteElement = AutoCompleteElements[i]; float info_xl, info_yl; Canvas->StrLen(Font, AutoCompleteElement, info_xl, info_yl); MaxWidth = FMath::Max(MaxWidth, info_xl); MaxHeight += yl; } int32 Border = 4; // white border ConsoleTile.Size = FVector2D( MaxWidth + 2 * Border, MaxHeight + 2 * Border ); ConsoleTile.SetColor( ConsoleDefs::BorderColor ); Canvas->DrawItem( ConsoleTile, UserInputLinePos.X + xl - Border, y + yl - MaxHeight - Border ); --Border; // dark inner part ConsoleTile.Size = FVector2D( MaxWidth + 2 * Border, MaxHeight + 2 * Border ); ConsoleTile.SetColor( ConsoleDefs::AutocompleteBackgroundColor ); Canvas->DrawItem( ConsoleTile, UserInputLinePos.X + xl - Border, y + yl - MaxHeight - Border ); } // auto completion elements for(int32 i = 0, Num = AutoCompleteElements.Num(); i < Num; ++i) { const FString& AutoCompleteElement = AutoCompleteElements[i]; if (i == AutoCompleteCursor // cursor line is highlighted || (Num >= MAX_AUTOCOMPLETION_LINES && i == Num - 1)) // e.g. [%i more matches] { ConsoleText.SetColor( ConsoleDefs::AutocompleteSuggestionColor ); } else { ConsoleText.SetColor( ConsoleDefs::AutocompletePartialSuggestionColor ); } ConsoleText.Text = FText::FromString(AutoCompleteElement); Canvas->DrawItem( ConsoleText, UserInputLinePos.X + xl, y ); y -= yl; } } // determine the cursor position OutStr = FString::Printf(TEXT("%s%s"), *ConsoleDefs::LeadingInputText, *TypedStr.Left(TypedStrPos)); Canvas->StrLen(Font, OutStr,xl,yl); // draw the cursor ConsoleText.SetColor( ConsoleDefs::CursorColor ); OutStr = FString::Printf( TEXT("_") ); ConsoleText.Text = FText::FromString( OutStr ); Canvas->DrawItem( ConsoleText, UserInputLinePos.X + xl, UserInputLinePos.Y-1.0f-yl ); }
void CreateSpritesFromTextures(TArray<UTexture2D*>& Textures) { const FString DefaultSuffix = TEXT("_Sprite"); FAssetToolsModule& AssetToolsModule = FModuleManager::Get().LoadModuleChecked<FAssetToolsModule>("AssetTools"); FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser"); TArray<UObject*> ObjectsToSync; for (auto TextureIt = Textures.CreateConstIterator(); TextureIt; ++TextureIt) { UTexture2D* Texture = *TextureIt; // Create the factory used to generate the sprite UPaperSpriteFactory* SpriteFactory = ConstructObject<UPaperSpriteFactory>(UPaperSpriteFactory::StaticClass()); SpriteFactory->InitialTexture = Texture; // Create the sprite FString Name; FString PackageName; if (!bExtractSprites) { // Get a unique name for the sprite AssetToolsModule.Get().CreateUniqueAssetName(Texture->GetOutermost()->GetName(), DefaultSuffix, /*out*/ PackageName, /*out*/ Name); const FString PackagePath = FPackageName::GetLongPackagePath(PackageName); if (UObject* NewAsset = AssetToolsModule.Get().CreateAsset(Name, PackagePath, UPaperSprite::StaticClass(), SpriteFactory)) { ObjectsToSync.Add(NewAsset); } } else { FScopedSlowTask Feedback(1, NSLOCTEXT("Paper2D", "Paper2D_ExtractSpritesFromTexture", "Extracting Sprites From Texture")); Feedback.MakeDialog(true); // First extract the rects from the texture TArray<FIntRect> ExtractedRects; UPaperSprite::ExtractRectsFromTexture(Texture, /*out*/ ExtractedRects); // Sort the rectangles by approximate row struct FRectangleSortHelper { FRectangleSortHelper(TArray<FIntRect>& InOutSprites) { // Sort by Y, then by X (top left corner), descending order (so we can use it as a stack from the top row down) TArray<FIntRect> SpritesLeft = InOutSprites; SpritesLeft.Sort([](const FIntRect& A, const FIntRect& B) { return (A.Min.Y == B.Min.Y) ? (A.Min.X > B.Min.X) : (A.Min.Y > B.Min.Y); }); InOutSprites.Reset(); // Start pulling sprites out, the first one in each row will dominate remaining ones and cause them to get labeled TArray<FIntRect> DominatedSprites; DominatedSprites.Empty(SpritesLeft.Num()); while (SpritesLeft.Num()) { FIntRect DominatingSprite = SpritesLeft.Pop(); DominatedSprites.Add(DominatingSprite); // Find the sprites that are dominated (intersect the infinite horizontal band described by the dominating sprite) for (int32 Index = 0; Index < SpritesLeft.Num();) { const FIntRect& CurElement = SpritesLeft[Index]; if ((CurElement.Min.Y <= DominatingSprite.Max.Y) && (CurElement.Max.Y >= DominatingSprite.Min.Y)) { DominatedSprites.Add(CurElement); SpritesLeft.RemoveAt(Index, /*Count=*/ 1, /*bAllowShrinking=*/ false); } else { ++Index; } } // Sort the sprites in the band by X and add them to the result DominatedSprites.Sort([](const FIntRect& A, const FIntRect& B) { return (A.Min.X < B.Min.X); }); InOutSprites.Append(DominatedSprites); DominatedSprites.Reset(); } } }; FRectangleSortHelper RectSorter(ExtractedRects); Feedback.TotalAmountOfWork = ExtractedRects.Num(); for (int ExtractedRectIndex = 0; ExtractedRectIndex < ExtractedRects.Num(); ++ExtractedRectIndex) { Feedback.EnterProgressFrame(1, NSLOCTEXT("Paper2D", "Paper2D_ExtractSpritesFromTexture", "Extracting Sprites From Texture")); FIntRect& ExtractedRect = ExtractedRects[ExtractedRectIndex]; SpriteFactory->bUseSourceRegion = true; SpriteFactory->InitialSourceUV = FVector2D(ExtractedRect.Min.X, ExtractedRect.Min.Y); SpriteFactory->InitialSourceDimension = FVector2D(ExtractedRect.Width(), ExtractedRect.Height()); // Get a unique name for the sprite const FString Suffix = FString::Printf(TEXT("%s_%d"), *DefaultSuffix, ExtractedRectIndex); AssetToolsModule.Get().CreateUniqueAssetName(Texture->GetOutermost()->GetName(), Suffix, /*out*/ PackageName, /*out*/ Name); const FString PackagePath = FPackageName::GetLongPackagePath(PackageName); if (UObject* NewAsset = AssetToolsModule.Get().CreateAsset(Name, PackagePath, UPaperSprite::StaticClass(), SpriteFactory)) { ObjectsToSync.Add(NewAsset); } if (GWarn->ReceivedUserCancel()) { break; } } } } if (ObjectsToSync.Num() > 0) { ContentBrowserModule.Get().SyncBrowserToAssets(ObjectsToSync); } }
void UConsole::BuildRuntimeAutoCompleteList(bool bForce) { #if !UE_BUILD_SHIPPING if (!bForce) { // unless forced delay updating until needed bIsRuntimeAutoCompleteUpToDate = false; return; } // clear the existing tree //@todo - probably only need to rebuild the tree + partial command list on level load for (int32 Idx = 0; Idx < AutoCompleteTree.ChildNodes.Num(); Idx++) { FAutoCompleteNode *Node = AutoCompleteTree.ChildNodes[Idx]; delete Node; } AutoCompleteTree.ChildNodes.Empty(); const UConsoleSettings* ConsoleSettings = GetDefault<UConsoleSettings>(); // copy the manual list first AutoCompleteList.Empty(); AutoCompleteList.AddZeroed(ConsoleSettings->ManualAutoCompleteList.Num()); for (int32 Idx = 0; Idx < ConsoleSettings->ManualAutoCompleteList.Num(); Idx++) { AutoCompleteList[Idx] = ConsoleSettings->ManualAutoCompleteList[Idx]; } // console variables { IConsoleManager::Get().ForEachConsoleObject( FConsoleObjectVisitor::CreateStatic< TArray<struct FAutoCompleteCommand>& >( &FConsoleVariableAutoCompleteVisitor::OnConsoleVariable, AutoCompleteList ) ); } // iterate through script exec functions and append to the list int32 ScriptExecCnt = 0; for (TObjectIterator<UFunction> It; It; ++It) { UFunction *Func = *It; // Determine whether or not this is a level script event that we can call (must be defined in the level script actor and not in parent, and has no return value) const UClass* FuncOuter = Cast<UClass>(Func->GetOuter()); const bool bIsLevelScriptFunction = FuncOuter && (FuncOuter->IsChildOf(ALevelScriptActor::StaticClass())) && (FuncOuter != ALevelScriptActor::StaticClass()) && (Func->ReturnValueOffset == MAX_uint16) && (Func->GetSuperFunction() == NULL); // exec functions that either have no parent, level script events, or are in the global state (filtering some unnecessary dupes) if ( (Func->HasAnyFunctionFlags(FUNC_Exec) && (Func->GetSuperFunction() == NULL || FuncOuter)) || bIsLevelScriptFunction) { FString FuncName = Func->GetName(); if(FDefaultValueHelper::HasWhitespaces(FuncName)) { FuncName = FString::Printf(TEXT("\"%s\""), *FuncName); } if( bIsLevelScriptFunction ) { FuncName = FString(TEXT("ce ")) + FuncName; } int32 NewIdx = AutoCompleteList.AddZeroed(1); AutoCompleteList[NewIdx].Command = FuncName; // build a help string // append each property (and it's type) to the help string for (TFieldIterator<UProperty> PropIt(Func); PropIt && (PropIt->PropertyFlags & CPF_Parm); ++PropIt) { UProperty *Prop = *PropIt; FuncName = FString::Printf(TEXT("%s %s[%s]"),*FuncName,*Prop->GetName(),*Prop->GetCPPType()); } AutoCompleteList[NewIdx].Desc = FuncName; ScriptExecCnt++; } } // enumerate maps TArray<FString> Packages; for (int32 PathIdx = 0; PathIdx < ConsoleSettings->AutoCompleteMapPaths.Num(); ++PathIdx) { FPackageName::FindPackagesInDirectory(Packages, FString::Printf(TEXT("%s%s"), *FPaths::GameDir(), *ConsoleSettings->AutoCompleteMapPaths[PathIdx])); } // also include maps in this user's developer dir FPackageName::FindPackagesInDirectory(Packages, FPaths::GameUserDeveloperDir()); for (int32 PackageIndex = 0; PackageIndex < Packages.Num(); PackageIndex++) { FString Pkg = Packages[PackageIndex]; int32 ExtIdx = Pkg.Find(*FPackageName::GetMapPackageExtension(),ESearchCase::IgnoreCase, ESearchDir::FromEnd); FString MapName; if (ExtIdx != INDEX_NONE && Pkg.Split(TEXT("/"),NULL,&MapName,ESearchCase::CaseSensitive, ESearchDir::FromEnd)) { // try to peel off the extension FString TrimmedMapName; if (!MapName.Split(TEXT("."),&TrimmedMapName,NULL,ESearchCase::CaseSensitive, ESearchDir::FromEnd)) { TrimmedMapName = MapName; } int32 NewIdx; // put _P maps at the front so that they match early, since those are generally the maps we want to actually open if (TrimmedMapName.EndsWith(TEXT("_P"))) { NewIdx = 0; AutoCompleteList.InsertZeroed(0,3); } else { NewIdx = AutoCompleteList.AddZeroed(3); } AutoCompleteList[NewIdx].Command = FString::Printf(TEXT("open %s"),*TrimmedMapName); AutoCompleteList[NewIdx].Desc = FString::Printf(TEXT("open %s"),*TrimmedMapName); AutoCompleteList[NewIdx+1].Command = FString::Printf(TEXT("travel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+1].Desc = FString::Printf(TEXT("travel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+2].Command = FString::Printf(TEXT("servertravel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+2].Desc = FString::Printf(TEXT("servertravel %s"),*TrimmedMapName); //MapNames.AddItem(Pkg); } } // misc commands { int32 NewIdx = AutoCompleteList.AddZeroed(1); AutoCompleteList[NewIdx].Command = FString(TEXT("open 127.0.0.1")); AutoCompleteList[NewIdx].Desc = FString(TEXT("open 127.0.0.1 (opens connection to localhost)")); } // build the magic tree! for (int32 ListIdx = 0; ListIdx < AutoCompleteList.Num(); ListIdx++) { FString Command = AutoCompleteList[ListIdx].Command.ToLower(); FAutoCompleteNode *Node = &AutoCompleteTree; for (int32 Depth = 0; Depth < Command.Len(); Depth++) { int32 Char = Command[Depth]; int32 FoundNodeIdx = INDEX_NONE; TArray<FAutoCompleteNode*> &NodeList = Node->ChildNodes; for (int32 NodeIdx = 0; NodeIdx < NodeList.Num(); NodeIdx++) { if (NodeList[NodeIdx]->IndexChar == Char) { FoundNodeIdx = NodeIdx; Node = NodeList[FoundNodeIdx]; NodeList[FoundNodeIdx]->AutoCompleteListIndices.Add(ListIdx); break; } } if (FoundNodeIdx == INDEX_NONE) { FAutoCompleteNode *NewNode = new FAutoCompleteNode(Char); NewNode->AutoCompleteListIndices.Add(ListIdx); Node->ChildNodes.Add(NewNode); Node = NewNode; } } } bIsRuntimeAutoCompleteUpToDate = true; //PrintNode(&AutoCompleteTree); #endif }
virtual bool Cook(FName Format, const TArray<uint8>& SrcBuffer, FSoundQualityInfo& QualityInfo, TArray<uint8>& CompressedDataStore) const override { check(Format == NAME_OGG); #if WITH_OGGVORBIS { short ReadBuffer[SAMPLES_TO_READ * SAMPLE_SIZE * 2]; ogg_stream_state os; // take physical pages, weld into a logical stream of packets ogg_page og; // one ogg bitstream page. Vorbis packets are inside ogg_packet op; // one raw packet of data for decode vorbis_info vi; // struct that stores all the static vorbis bitstream settings vorbis_comment vc; // struct that stores all the user comments vorbis_dsp_state vd; // central working state for the packet->PCM decoder vorbis_block vb; // local working space for packet->PCM decode uint32 i; bool eos; // Create a buffer to store compressed data CompressedDataStore.Empty(); FMemoryWriter CompressedData( CompressedDataStore ); uint32 BufferOffset = 0; float CompressionQuality = ( float )( QualityInfo.Quality * VORBIS_QUALITY_MODIFIER ) / 100.0f; CompressionQuality = FMath::Clamp( CompressionQuality, -0.1f, 1.0f ); vorbis_info_init( &vi ); if( vorbis_encode_init_vbr( &vi, QualityInfo.NumChannels, QualityInfo.SampleRate, CompressionQuality ) ) { return false; } // add a comment vorbis_comment_init( &vc ); vorbis_comment_add_tag( &vc, "ENCODER", "UnrealEngine4" ); // set up the analysis state and auxiliary encoding storage vorbis_analysis_init( &vd, &vi ); vorbis_block_init( &vd, &vb ); // set up our packet->stream encoder ogg_stream_init( &os, 0 ); ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout( &vd, &vc, &header, &header_comm, &header_code); ogg_stream_packetin( &os, &header ); ogg_stream_packetin( &os, &header_comm ); ogg_stream_packetin( &os, &header_code ); // This ensures the actual audio data will start on a new page, as per spec while( true ) { int result = ogg_stream_flush( &os, &og ); if( result == 0 ) { break; } CompressedData.Serialize( og.header, og.header_len ); CompressedData.Serialize( og.body, og.body_len ); } eos = false; while( !eos ) { // Read samples uint32 BytesToRead = FMath::Min( SAMPLES_TO_READ * QualityInfo.NumChannels * SAMPLE_SIZE, QualityInfo.SampleDataSize - BufferOffset ); FMemory::Memcpy( ReadBuffer, SrcBuffer.GetData() + BufferOffset, BytesToRead ); BufferOffset += BytesToRead; if( BytesToRead == 0) { // end of file vorbis_analysis_wrote( &vd, 0 ); } else { // expose the buffer to submit data float **buffer = vorbis_analysis_buffer( &vd, SAMPLES_TO_READ ); if( QualityInfo.NumChannels == 1 ) { for( i = 0; i < BytesToRead / SAMPLE_SIZE; i++ ) { buffer[0][i] = ( ReadBuffer[i] ) / 32768.0f; } } else { for( i = 0; i < BytesToRead / ( SAMPLE_SIZE * 2 ); i++ ) { buffer[0][i] = ( ReadBuffer[i * 2] ) / 32768.0f; buffer[1][i] = ( ReadBuffer[i * 2 + 1] ) / 32768.0f; } } // tell the library how many samples we actually submitted vorbis_analysis_wrote( &vd, i ); } // vorbis does some data preanalysis, then divvies up blocks for more involved (potentially parallel) processing. while( vorbis_analysis_blockout( &vd, &vb ) == 1 ) { // analysis, assume we want to use bitrate management vorbis_analysis( &vb, NULL ); vorbis_bitrate_addblock( &vb ); while( vorbis_bitrate_flushpacket( &vd, &op ) ) { // weld the packet into the bitstream ogg_stream_packetin( &os, &op ); // write out pages (if any) while( !eos ) { int result = ogg_stream_pageout( &os, &og ); if( result == 0 ) { break; } CompressedData.Serialize( og.header, og.header_len ); CompressedData.Serialize( og.body, og.body_len ); // this could be set above, but for illustrative purposes, I do it here (to show that vorbis does know where the stream ends) if( ogg_page_eos( &og ) ) { eos = true; } } } } } // clean up and exit. vorbis_info_clear() must be called last ogg_stream_clear( &os ); vorbis_block_clear( &vb ); vorbis_dsp_clear( &vd ); vorbis_comment_clear( &vc ); vorbis_info_clear( &vi ); // ogg_page and ogg_packet structs always point to storage in libvorbis. They're never freed or manipulated directly } return CompressedDataStore.Num() > 0; #else return false; #endif // WITH_OGGVOBVIS }
/** * Create the proper query for the master server based on the given search settings * * @param OutFilter Steam structure containing the proper filters * @param NumFilters number of filters contained in the array above */ void FOnlineAsyncTaskSteamFindServerBase::CreateQuery(MatchMakingKeyValuePair_t** OutFilter, int32& NumFilters) { // Copy the params so we can remove the values as we use them FOnlineSearchSettings TempSearchSettings = SearchSettings->QuerySettings; // Include enough space for all search parameters plus the required one "gamedir" below int32 MaxFilters = TempSearchSettings.SearchParams.Num() + 1; *OutFilter = new MatchMakingKeyValuePair_t[MaxFilters]; MatchMakingKeyValuePair_t* Filters = *OutFilter; int32 KeySize = sizeof(Filters[0].m_szKey); int32 ValueSize = sizeof(Filters[0].m_szValue); NumFilters = 0; // Filter must match at least our game FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "gamedir", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, STEAMGAMEDIR, ValueSize); NumFilters++; FString MapName; if (TempSearchSettings.Get(SETTING_MAPNAME, MapName) && !MapName.IsEmpty()) { // Server passes the filter if the server is playing the specified map. FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "map", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, TCHAR_TO_ANSI(*MapName), ValueSize); NumFilters++; } TempSearchSettings.SearchParams.Remove(SETTING_MAPNAME); FString HostIp; if (TempSearchSettings.Get(SEARCH_STEAM_HOSTIP, HostIp) && !HostIp.IsEmpty()) { // Server passes the filter if it passed a valid host ip. FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "gameaddr", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, TCHAR_TO_ANSI(*HostIp), ValueSize); NumFilters++; } TempSearchSettings.SearchParams.Remove(SEARCH_STEAM_HOSTIP); int32 DedicatedOnly = 0; if (TempSearchSettings.Get(SEARCH_DEDICATED_ONLY, DedicatedOnly) && DedicatedOnly != 0) { // Server passes the filter if it passed true to SetDedicatedServer. FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "dedicated", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, "true", ValueSize); NumFilters++; } TempSearchSettings.SearchParams.Remove(SEARCH_DEDICATED_ONLY); int32 SecureOnly = 0; if (TempSearchSettings.Get(SEARCH_SECURE_SERVERS_ONLY, SecureOnly) && SecureOnly != 0) { // Server passes the filter if the server is VAC-enabled. FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "secure", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, "true", ValueSize); NumFilters++; } TempSearchSettings.SearchParams.Remove(SEARCH_SECURE_SERVERS_ONLY); int32 EmptyOnly = 0; if (TempSearchSettings.Get(SEARCH_EMPTY_SERVERS_ONLY, EmptyOnly) && EmptyOnly != 0) { // Server passes the filter if it doesn't have any players. FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "noplayers", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, "true", ValueSize); NumFilters++; } TempSearchSettings.SearchParams.Remove(SEARCH_EMPTY_SERVERS_ONLY); // TEMP!!!! return; /** * "full" - not full * "empty" - not empty * "proxy" - a relay server */ if (NumFilters <= MaxFilters) { /** Filter out key value pairs */ TArray<FString> Clauses; FString CurrentClause; for (FSearchParams::TConstIterator It(TempSearchSettings.SearchParams); It; ++It) { const FName Key = It.Key(); const FOnlineSessionSearchParam& SearchParam = It.Value(); FString KeyStr; if (SessionKeyToSteamKey(Key, SearchParam.Data, KeyStr)) { if (SearchParam.ComparisonOp == EOnlineComparisonOp::Equals) { FString NewParam = FString::Printf(TEXT("%s:%s"), *KeyStr, *SearchParam.Data.ToString()); if (NewParam.Len() <= ValueSize) { if (NewParam.Len() + CurrentClause.Len() < ValueSize) { if (CurrentClause.IsEmpty()) { CurrentClause = NewParam; } else { // Continue to add to the clause CurrentClause = CurrentClause + "," + NewParam; } } else { // Create a new clause Clauses.Add(CurrentClause); CurrentClause = NewParam; } } else { UE_LOG_ONLINE(Warning, TEXT("Skipping search clause due to size: %s"), *NewParam); } } } } // Add the remainder clause if (!CurrentClause.IsEmpty()) { Clauses.Add(CurrentClause); } if (Clauses.Num() > 0) { // Make sure there is room (Clauses + "and" clause if more than one) if (NumFilters + Clauses.Num() + (Clauses.Num() > 1 ? 1 : 0) <= MaxFilters) { if (Clauses.Num() > 1) { // "and" (x1 && x2 && ... && xn) where n is number of clauses FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "and", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, TCHAR_TO_UTF8(*FString::FromInt(Clauses.Num())), ValueSize); NumFilters++; for (int32 ClauseIdx=0; ClauseIdx < Clauses.Num(); ClauseIdx++) { // Server passes the filter if the server's game data (ISteamGameServer::SetGameData) contains all of the // specified strings. The value field is a comma-delimited list of strings to match. FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "gamedataand", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, TCHAR_TO_UTF8(*Clauses[ClauseIdx]), ValueSize); NumFilters++; } } else { // Server passes the filter if the server's game data (ISteamGameServer::SetGameData) contains all of the // specified strings. The value field is a comma-delimited list of strings to match. FCStringAnsi::Strncpy(Filters[NumFilters].m_szKey, "gamedataand", KeySize); FCStringAnsi::Strncpy(Filters[NumFilters].m_szValue, TCHAR_TO_UTF8(*Clauses[0]), ValueSize); NumFilters++; } } } } }
void FSpriteDetailsCustomization::BuildCollisionSection(IDetailCategoryBuilder& CollisionCategory, IDetailLayoutBuilder& DetailLayout) { TSharedPtr<IPropertyHandle> SpriteCollisionDomainProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, SpriteCollisionDomain)); CollisionCategory.HeaderContent ( SNew(SBox) .HAlign(HAlign_Right) [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .Padding(FMargin(5.0f, 0.0f)) .AutoWidth() [ SNew(STextBlock) .Font(FEditorStyle::GetFontStyle("TinyText")) .Text(this, &FSpriteDetailsCustomization::GetCollisionHeaderContentText, SpriteCollisionDomainProperty) ] ] ); TAttribute<EVisibility> ParticipatesInPhysics = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP( this, &FSpriteDetailsCustomization::AnyPhysicsMode, SpriteCollisionDomainProperty)); TAttribute<EVisibility> ParticipatesInPhysics3D = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::PhysicsModeMatches, SpriteCollisionDomainProperty, ESpriteCollisionMode::Use3DPhysics)); TAttribute<EVisibility> HideWhenInRenderingMode = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::EditorModeIsNot, ESpriteEditorMode::EditRenderingGeomMode)); TAttribute<EVisibility> ShowWhenInRenderingMode = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::EditorModeMatches, ESpriteEditorMode::EditRenderingGeomMode)); static const FText EditCollisionInCollisionMode = LOCTEXT("CollisionPropertiesHiddenInRenderingMode", "Switch to 'Edit Collsion' mode\nto edit Collision settings"); CollisionCategory.AddCustomRow(EditCollisionInCollisionMode) .Visibility(ShowWhenInRenderingMode) .WholeRowContent() .HAlign(HAlign_Center) [ SNew(STextBlock) .Font(DetailLayout.GetDetailFontItalic()) .Justification(ETextJustify::Center) .Text(EditCollisionInCollisionMode) ]; CollisionCategory.AddProperty(SpriteCollisionDomainProperty).Visibility(HideWhenInRenderingMode); // Add the collision geometry mode into the parent container (renamed) { // Restrict the diced value TSharedPtr<FPropertyRestriction> PreventDicedRestriction = MakeShareable(new FPropertyRestriction(LOCTEXT("CollisionGeometryDoesNotSupportDiced", "Collision geometry can not be set to Diced"))); const UEnum* const SpritePolygonModeEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("ESpritePolygonMode")); PreventDicedRestriction->AddDisabledValue(SpritePolygonModeEnum->GetNameStringByValue((uint8)ESpritePolygonMode::Diced)); // Find and add the property const FString CollisionGeometryTypePropertyPath = FString::Printf(TEXT("%s.%s"), GET_MEMBER_NAME_STRING_CHECKED(UPaperSprite, CollisionGeometry), GET_MEMBER_NAME_STRING_CHECKED(FSpriteGeometryCollection, GeometryType)); TSharedPtr<IPropertyHandle> CollisionGeometryTypeProperty = DetailLayout.GetProperty(*CollisionGeometryTypePropertyPath); CollisionGeometryTypeProperty->AddRestriction(PreventDicedRestriction.ToSharedRef()); CollisionCategory.AddProperty(CollisionGeometryTypeProperty) .DisplayName(LOCTEXT("CollisionGeometryType", "Collision Geometry Type")) .Visibility(ParticipatesInPhysics); } // Show the collision thickness only in 3D mode CollisionCategory.AddProperty( DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, CollisionThickness)) ) .Visibility(ParticipatesInPhysics3D); // Show the default body instance (and only it) from the body setup (if it exists) DetailLayout.HideProperty("BodySetup"); IDetailPropertyRow& BodySetupDefaultInstance = CollisionCategory.AddProperty("BodySetup.DefaultInstance"); TArray<TWeakObjectPtr<UObject>> SpritesBeingEdited; DetailLayout.GetObjectsBeingCustomized(/*out*/ SpritesBeingEdited); TArray<UObject*> BodySetupList; for (auto WeakSpritePtr : SpritesBeingEdited) { if (UPaperSprite* Sprite = Cast<UPaperSprite>(WeakSpritePtr.Get())) { if (UBodySetup* BodySetup = Sprite->BodySetup) { BodySetupList.Add(BodySetup); } } } if (BodySetupList.Num() > 0) { IDetailPropertyRow* DefaultInstanceRow = CollisionCategory.AddExternalObjectProperty(BodySetupList, GET_MEMBER_NAME_CHECKED(UBodySetup, DefaultInstance)); if (DefaultInstanceRow != nullptr) { DefaultInstanceRow->Visibility(ParticipatesInPhysics); } } // Show the collision geometry when not None CollisionCategory.AddProperty(DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, CollisionGeometry))) .Visibility(ParticipatesInPhysics); // Add the collision polygons into advanced (renamed) const FString CollisionGeometryPolygonsPropertyPath = FString::Printf(TEXT("%s.%s"), GET_MEMBER_NAME_STRING_CHECKED(UPaperSprite, CollisionGeometry), GET_MEMBER_NAME_STRING_CHECKED(FSpriteGeometryCollection, Shapes)); CollisionCategory.AddProperty(DetailLayout.GetProperty(*CollisionGeometryPolygonsPropertyPath), EPropertyLocation::Advanced) .DisplayName(LOCTEXT("CollisionShapes", "Collision Shapes")) .Visibility(ParticipatesInPhysics); }
int32 FMessageTracer::GetEndpoints( TArray<FMessageTracerEndpointInfoPtr>& OutEndpoints ) const { RecipientsToEndpointInfos.GenerateValueArray(OutEndpoints); return OutEndpoints.Num(); }