Пример #1
2
/**
 * 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;
}
Пример #2
0
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 );
	}
}
Пример #3
0
/**
 * 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 );
}
Пример #5
0
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());
	}
}
Пример #6
0
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();
}
Пример #7
0
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;
}