/** * Creates a static mesh object from raw triangle data. */ UStaticMesh* CreateStaticMesh(struct FRawMesh& RawMesh,TArray<UMaterialInterface*>& Materials,UObject* InOuter,FName InName) { // Create the UStaticMesh object. FStaticMeshComponentRecreateRenderStateContext RecreateRenderStateContext(FindObject<UStaticMesh>(InOuter,*InName.ToString())); UStaticMesh* StaticMesh = new(InOuter,InName,RF_Public|RF_Standalone) UStaticMesh(FPostConstructInitializeProperties()); // Add one LOD for the base mesh FStaticMeshSourceModel* SrcModel = new(StaticMesh->SourceModels) FStaticMeshSourceModel(); SrcModel->RawMeshBulkData->SaveRawMesh(RawMesh); StaticMesh->Materials = Materials; int32 NumSections = StaticMesh->Materials.Num(); // Set up the SectionInfoMap to enable collision for (int32 SectionIdx = 0; SectionIdx < NumSections; ++SectionIdx) { FMeshSectionInfo Info = StaticMesh->SectionInfoMap.Get(0, SectionIdx); Info.MaterialIndex = SectionIdx; Info.bEnableCollision = true; StaticMesh->SectionInfoMap.Set(0, SectionIdx, Info); } StaticMesh->Build(); StaticMesh->MarkPackageDirty(); return StaticMesh; }
void DecomposeUCXMesh( const TArray<FVector>& CollisionVertices, const TArray<int32>& CollisionFaceIdx, UBodySetup* BodySetup ) { // We keep no ref to this Model, so it will be GC'd at some point after the import. UModel* TempModel = new UModel(FPostConstructInitializeProperties(),NULL,1); FMeshConnectivityBuilder ConnectivityBuilder; // Send triangles to connectivity builder for(int32 x = 0;x < CollisionFaceIdx.Num();x += 3) { const FVector &VertexA = CollisionVertices[ CollisionFaceIdx[x + 2] ]; const FVector &VertexB = CollisionVertices[ CollisionFaceIdx[x + 1] ]; const FVector &VertexC = CollisionVertices[ CollisionFaceIdx[x + 0] ]; ConnectivityBuilder.AddTriangle( VertexA, VertexB, VertexC ); } ConnectivityBuilder.CreateConnectivityGroups(); // For each valid group build BSP and extract convex hulls for ( int32 i=0; i<ConnectivityBuilder.Groups.Num(); i++ ) { const FMeshConnectivityGroup &Group = ConnectivityBuilder.Groups[ i ]; // TODO: add some BSP friendly checks here // e.g. if group triangles form a closed mesh // Generate polygons from group triangles TempModel->Polys->Element.Empty(); for ( int32 j=0; j<Group.Triangles.Num(); j++ ) { const FMeshConnectivityTriangle &Triangle = ConnectivityBuilder.Triangles[ Group.Triangles[j] ]; FPoly* Poly = new( TempModel->Polys->Element ) FPoly(); Poly->Init(); Poly->iLink = j / 3; // Add vertices new( Poly->Vertices ) FVector( ConnectivityBuilder.Vertices[ Triangle.Vertices[0] ].Position ); new( Poly->Vertices ) FVector( ConnectivityBuilder.Vertices[ Triangle.Vertices[1] ].Position ); new( Poly->Vertices ) FVector( ConnectivityBuilder.Vertices[ Triangle.Vertices[2] ].Position ); // Update polygon normal Poly->CalcNormal(1); } // Build bounding box. TempModel->BuildBound(); // Build BSP for the brush. FBSPOps::bspBuild( TempModel,FBSPOps::BSP_Good,15,70,1,0 ); FBSPOps::bspRefresh( TempModel, 1 ); FBSPOps::bspBuildBounds( TempModel ); // Convert collision model into a collection of convex hulls. // Generated convex hulls will be added to existing ones BodySetup->CreateFromModel( TempModel, false ); } }
/** * Duplicates the specified brush and makes it into a CSG-able level brush. * @return The new brush, or NULL if the original was empty. */ void FBSPOps::csgCopyBrush( ABrush* Dest, ABrush* Src, uint32 PolyFlags, EObjectFlags ResFlags, bool bNeedsPrep, bool bCopyPosRotScale, bool bAllowEmpty ) { check(Src); check(Src->BrushComponent); check(Src->Brush); // Handle empty brush. if( !bAllowEmpty && !Src->Brush->Polys->Element.Num() ) { Dest->Brush = NULL; Dest->BrushComponent->Brush = NULL; return; } // Duplicate the brush and its polys. Dest->PolyFlags = PolyFlags; Dest->Brush = new( Dest, NAME_None, ResFlags )UModel(FPostConstructInitializeProperties(), NULL, Src->Brush->RootOutside ); Dest->Brush->Polys = new( Dest->Brush, NAME_None, ResFlags )UPolys(FPostConstructInitializeProperties()); check(Dest->Brush->Polys->Element.GetOwner()==Dest->Brush->Polys); Dest->Brush->Polys->Element.AssignButKeepOwner(Src->Brush->Polys->Element); check(Dest->Brush->Polys->Element.GetOwner()==Dest->Brush->Polys); Dest->BrushComponent->Brush = Dest->Brush; if(Src->BrushBuilder != nullptr) { Dest->BrushBuilder = DuplicateObject<UBrushBuilder>(Src->BrushBuilder, Dest); } // Update poly textures. for( int32 i=0; i<Dest->Brush->Polys->Element.Num(); i++ ) { Dest->Brush->Polys->Element[i].iBrushPoly = INDEX_NONE; } // Copy positioning, and build bounding box. if(bCopyPosRotScale) { Dest->CopyPosRotScaleFrom( Src ); } // If it's a moving brush, prep it. if( bNeedsPrep ) { csgPrepMovingBrush( Dest ); } }
UTransactor* UEditorEngine::CreateTrans() { int32 UndoBufferSize; if( !GConfig->GetInt( TEXT("Undo"), TEXT("UndoBufferSize"), UndoBufferSize, GEditorUserSettingsIni ) ) { UndoBufferSize = 16; } return new UTransBuffer( FPostConstructInitializeProperties(),UndoBufferSize*1024*1024 ); }
void UPackageMap::PostInitProperties() { Super::PostInitProperties(); bShouldSerializeUnAckedObjects = true; bSerializedUnAckedObject = false; // Create the NetGUIDCache now if we don't have one. The pattern should be that the MasterMap (a plain UPackageMap) will always // create one here, but UPackageMapClient and other subclasses will take thier Cache in as a parameter so that is it shared // (e.g., one 1 UNetGUIDCache exists on the server and is referenced be each client connection's package map). // // This also keeps subclasses from <i>requiring</i> a master map to pass in their UNetGUIDCache; if we don't pass one in on construction // they can use their own and still work. This may be useful for 'sideways' connections or other backend communication if ( !Cache && !HasAnyFlags(RF_ClassDefaultObject) ) { Cache = new UNetGUIDCache (FPostConstructInitializeProperties()); } }
void FShadowMapPendingTexture::StartEncoding(UWorld* InWorld) { // Create the shadow-map texture. UShadowMapTexture2D* Texture = new(Outer) UShadowMapTexture2D(FPostConstructInitializeProperties()); Texture->Filter = GUseBilinearLightmaps ? TF_Default : TF_Nearest; // Signed distance field textures get stored in linear space, since they need more precision near .5. Texture->SRGB = false; Texture->LODGroup = TEXTUREGROUP_Shadowmap; Texture->ShadowmapFlags = ShadowmapFlags; Texture->Source.Init2DWithMipChain(GetSizeX(), GetSizeY(), TSF_BGRA8); Texture->MipGenSettings = TMGS_LeaveExistingMips; Texture->CompressionNone = true; int32 TextureSizeX = Texture->Source.GetSizeX(); int32 TextureSizeY = Texture->Source.GetSizeY(); { // Create the uncompressed top mip-level. TArray< TArray<FFourDistanceFieldSamples> > MipData; FShadowMap2D::EncodeSingleTexture(*this, Texture, MipData); // Copy the mip-map data into the UShadowMapTexture2D's mip-map array. for(int32 MipIndex = 0;MipIndex < MipData.Num();MipIndex++) { FColor* DestMipData = (FColor*)Texture->Source.LockMip(MipIndex); uint32 MipSizeX = FMath::Max(1,TextureSizeX >> MipIndex); uint32 MipSizeY = FMath::Max(1,TextureSizeY >> MipIndex); for(uint32 Y = 0;Y < MipSizeY;Y++) { for(uint32 X = 0;X < MipSizeX;X++) { const FFourDistanceFieldSamples& SourceSample = MipData[MipIndex][Y * MipSizeX + X]; DestMipData[ Y * MipSizeX + X ] = FColor(SourceSample.Samples[0].Distance, SourceSample.Samples[1].Distance, SourceSample.Samples[2].Distance, SourceSample.Samples[3].Distance); } } Texture->Source.UnlockMip(MipIndex); } } // Update stats. int32 TextureSize = Texture->CalcTextureMemorySizeEnum( TMC_AllMips ); GNumShadowmapTotalTexels += TextureSizeX * TextureSizeY; GNumShadowmapTextures++; GShadowmapTotalSize += TextureSize; GShadowmapTotalStreamingSize += (ShadowmapFlags & SMF_Streamed) ? TextureSize : 0; UPackage* TexturePackage = Texture->GetOutermost(); for ( int32 LevelIndex=0; TexturePackage && LevelIndex < InWorld->GetNumLevels(); LevelIndex++ ) { ULevel* Level = InWorld->GetLevel(LevelIndex); UPackage* LevelPackage = Level->GetOutermost(); if ( TexturePackage == LevelPackage ) { Level->ShadowmapTotalSize += float(TextureSize) / 1024.0f; break; } } // Update the texture resource. Texture->BeginCachePlatformData(); Texture->FinishCachePlatformData(); Texture->UpdateResource(); }
bool UDemoNetDriver::InitConnect( FNetworkNotify* InNotify, const FURL& ConnectURL, FString& Error ) { // handle default initialization if ( !InitBase( true, InNotify, ConnectURL, false, Error ) ) { return false; } // open the pre-recorded demo file FileAr = IFileManager::Get().CreateFileReader( *DemoFilename ); if ( !FileAr ) { Error = FString::Printf( TEXT( "Couldn't open demo file %s for reading" ), *DemoFilename ); UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: %s" ), *Error ); return false; } // Playback, local machine is a client, and the demo stream acts "as if" it's the server. ServerConnection = ConstructObject<UNetConnection>( UDemoNetConnection::StaticClass() ); ServerConnection->InitConnection( this, USOCK_Pending, ConnectURL, 1000000 ); #if 1 // Create fake control channel ServerConnection->CreateChannel( CHTYPE_Control, 1 ); #endif // use the same byte format regardless of platform so that the demos are cross platform // DEMO_FIXME: This is messing up for some reason, investigate //FileAr->SetByteSwapping( true ); int32 EngineVersion = 0; (*FileAr) << EngineVersion; (*FileAr) << PlaybackTotalFrames; UE_LOG( LogDemo, Log, TEXT( "Starting demo playback with demo. Filename: %s, Frames: %i, Version %i" ), *DemoFilename, PlaybackTotalFrames, EngineVersion ); #if 1 // Bypass UDemoPendingNetLevel FString LevelName; (*FileAr) << LevelName; FString LoadMapError; FURL DemoURL; DemoURL.Map = LevelName; FWorldContext * WorldContext = GEngine->GetWorldContextFromWorld( World ); if ( WorldContext == NULL ) { Error = FString::Printf( TEXT( "No world context" ), *DemoFilename ); UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: %s" ), *Error ); return false; } World->DemoNetDriver = NULL; SetWorld( NULL ); UDemoPendingNetGame * NewPendingNetGame = new UDemoPendingNetGame( FPostConstructInitializeProperties() ); NewPendingNetGame->DemoNetDriver = this; WorldContext->PendingNetGame = NewPendingNetGame; if ( !GEngine->LoadMap( *WorldContext, DemoURL, NewPendingNetGame, LoadMapError ) ) { Error = LoadMapError; UE_LOG( LogDemo, Error, TEXT( "UDemoNetDriver::InitConnect: LoadMap failed: failed: %s" ), *Error ); return false; } SetWorld( WorldContext->World() ); WorldContext->World()->DemoNetDriver = this; WorldContext->PendingNetGame = NULL; #endif int32 NumStreamingLevels = 0; (*FileAr) << NumStreamingLevels; for ( int32 i = 0; i < NumStreamingLevels; ++i ) { ULevelStreamingKismet* StreamingLevel = static_cast<ULevelStreamingKismet*>(StaticConstructObject(ULevelStreamingKismet::StaticClass(), GetWorld(), NAME_None, RF_NoFlags, NULL ) ); StreamingLevel->bShouldBeLoaded = true; StreamingLevel->bShouldBeVisible = true; StreamingLevel->bShouldBlockOnLoad = false; StreamingLevel->bInitiallyLoaded = true; StreamingLevel->bInitiallyVisible = true; FString PackageName; FString PackageNameToLoad; (*FileAr) << PackageName; (*FileAr) << PackageNameToLoad; (*FileAr) << StreamingLevel->LevelTransform; StreamingLevel->PackageNameToLoad = FName( *PackageNameToLoad ); StreamingLevel->SetWorldAssetByPackageName( FName( *PackageName ) ); GetWorld()->StreamingLevels.Add( StreamingLevel ); UE_LOG( LogDemo, Log, TEXT( " Loading streamingLevel: %s, %s" ), *PackageName, *PackageNameToLoad ); } DemoDeltaTime = 0; return true; }
UObject* USoundModImporterFactory::FactoryCreateBinary ( UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, const TCHAR* FileType, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn ) { // if the sound already exists, remember the user settings USoundMod* ExistingSound = FindObject<USoundMod>(InParent, *Name.ToString()); // TODO - Audio Threading. This needs to be sent to the audio device and wait on stopping the sounds TArray<UAudioComponent*> ComponentsToRestart; FAudioDevice* AudioDevice = GEngine->GetAudioDevice(); if (AudioDevice && ExistingSound) { // TODO: Generalize the stop sounds function //AudioDevice->StopSoundsForReimport(ExistingSound, ComponentsToRestart); } bool bUseExistingSettings = bSoundModFactorySuppressImportOverwriteDialog; if (ExistingSound && !bUseExistingSettings && !GIsAutomationTesting) { // Prompt the user for what to do if a 'To All' response wasn't already given. if (OverwriteYesOrNoToAllState != EAppReturnType::YesAll && OverwriteYesOrNoToAllState != EAppReturnType::NoAll) { OverwriteYesOrNoToAllState = FMessageDialog::Open(EAppMsgType::YesNoYesAllNoAllCancel, FText::Format( NSLOCTEXT("UnrealEd", "ImportedSoundAlreadyExists_F", "You are about to import '{0}' over an existing sound. Would you like to overwrite the existing settings?\n\nYes or Yes to All: Overwrite the existing settings.\nNo or No to All: Preserve the existing settings.\nCancel: Abort the operation."), FText::FromName(Name))); } switch (OverwriteYesOrNoToAllState) { case EAppReturnType::Yes: case EAppReturnType::YesAll: { // Overwrite existing settings bUseExistingSettings = false; break; } case EAppReturnType::No: case EAppReturnType::NoAll: { // Preserve existing settings bUseExistingSettings = true; break; } default: { FEditorDelegates::OnAssetPostImport.Broadcast(this, NULL); return NULL; } } } // Reset the flag back to false so subsequent imports are not suppressed unless the code explicitly suppresses it bSoundModFactorySuppressImportOverwriteDialog = false; TArray<uint8> RawModData; RawModData.Empty(BufferEnd - Buffer); RawModData.AddUninitialized(BufferEnd - Buffer); FMemory::Memcpy(RawModData.GetData(), Buffer, RawModData.Num()); // TODO: Validate that this is actually a mod file xmp_context xmpContext = xmp_create_context(); if (xmp_load_module_from_memory(xmpContext, RawModData.GetData(), RawModData.Num()) != 0) { return NULL; } xmp_module_info xmpModuleInfo; xmp_get_module_info(xmpContext, &xmpModuleInfo); // Use pre-existing sound if it exists and we want to keep settings, // otherwise create new sound and import raw data. USoundMod* Sound = (bUseExistingSettings && ExistingSound) ? ExistingSound : new(InParent, Name, Flags) USoundMod(FPostConstructInitializeProperties()); Sound->Duration = xmpModuleInfo.seq_data->duration / 1000.f; xmp_release_module(xmpContext); xmp_free_context(xmpContext); Sound->RawData.Lock(LOCK_READ_WRITE); void* LockedData = Sound->RawData.Realloc(BufferEnd - Buffer); FMemory::Memcpy(LockedData, Buffer, BufferEnd - Buffer); Sound->RawData.Unlock(); FEditorDelegates::OnAssetPostImport.Broadcast(this, Sound); for (int32 ComponentIndex = 0; ComponentIndex < ComponentsToRestart.Num(); ++ComponentIndex) { ComponentsToRestart[ComponentIndex]->Play(); } return Sound; }