2015-06-18 06:59:14 -04:00
|
|
|
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "GeometryCacheModulePrivatePCH.h"
|
|
|
|
|
#include "GeometryCacheComponent.h"
|
2015-09-07 09:32:51 -04:00
|
|
|
#include "MessageLog.h"
|
|
|
|
|
#include "ContentStreaming.h"
|
2015-06-18 06:59:14 -04:00
|
|
|
|
|
|
|
|
#include "GeometryCacheSceneProxy.h"
|
|
|
|
|
#include "GeometryCacheTrack.h"
|
|
|
|
|
#include "GeometryCacheTrackFlipbookAnimation.h"
|
|
|
|
|
|
2015-09-07 09:32:51 -04:00
|
|
|
#define LOCTEXT_NAMESPACE "GeometryCacheComponent"
|
|
|
|
|
|
2015-06-18 06:59:14 -04:00
|
|
|
DECLARE_CYCLE_STAT(TEXT("GeometryCacheTick"), STAT_GeometryCacheComponent_TickComponent, STATGROUP_GeometryCache);
|
|
|
|
|
|
|
|
|
|
UGeometryCacheComponent::UGeometryCacheComponent(const FObjectInitializer& ObjectInitializer)
|
|
|
|
|
: Super(ObjectInitializer)
|
|
|
|
|
{
|
|
|
|
|
PrimaryComponentTick.bCanEverTick = true;
|
|
|
|
|
ElapsedTime = 0.0f;
|
|
|
|
|
bRunning = false;
|
|
|
|
|
bLooping = true;
|
|
|
|
|
PlayDirection = 1.0f;
|
|
|
|
|
StartTimeOffset = 0.0f;
|
|
|
|
|
PlaybackSpeed = 1.0f;
|
|
|
|
|
Duration = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::BeginDestroy()
|
|
|
|
|
{
|
|
|
|
|
Super::BeginDestroy();
|
|
|
|
|
ReleaseResources();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::OnRegister()
|
2015-09-07 09:32:51 -04:00
|
|
|
{
|
|
|
|
|
ClearTrackData();
|
|
|
|
|
SetupTrackData();
|
|
|
|
|
Super::OnRegister();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::ClearTrackData()
|
2015-06-18 06:59:14 -04:00
|
|
|
{
|
|
|
|
|
NumTracks = 0;
|
|
|
|
|
TrackMatrixSampleIndices.Empty();
|
|
|
|
|
TrackMatrixSampleIndices.Empty();
|
|
|
|
|
TrackSections.Empty();
|
2015-09-07 09:32:51 -04:00
|
|
|
SceneProxy = nullptr;
|
|
|
|
|
}
|
2015-06-18 06:59:14 -04:00
|
|
|
|
2015-09-07 09:32:51 -04:00
|
|
|
void UGeometryCacheComponent::SetupTrackData()
|
|
|
|
|
{
|
|
|
|
|
if (GeometryCache != nullptr)
|
2015-06-18 06:59:14 -04:00
|
|
|
{
|
|
|
|
|
// Refresh NumTracks and clear Index Arrays
|
2015-09-07 09:32:51 -04:00
|
|
|
NumTracks = GeometryCache->Tracks.Num();
|
2015-06-18 06:59:14 -04:00
|
|
|
TrackMeshSampleIndices.Empty(GeometryCache->Tracks.Num());
|
|
|
|
|
TrackMatrixSampleIndices.Empty(GeometryCache->Tracks.Num());
|
|
|
|
|
|
|
|
|
|
Duration = 0.0f;
|
|
|
|
|
// Create mesh sections for each GeometryCacheTrack
|
2015-09-07 09:32:51 -04:00
|
|
|
for (int32 TrackIndex = 0; TrackIndex < NumTracks; ++TrackIndex)
|
|
|
|
|
{
|
|
|
|
|
UGeometryCacheTrack* Track = GeometryCache->Tracks[TrackIndex];
|
2015-06-18 06:59:14 -04:00
|
|
|
FMatrix WorldMatrix;
|
|
|
|
|
int32 MeshSampleIndex = -1;
|
|
|
|
|
int32 MatrixSampleIndex = -1;
|
2015-09-07 09:32:51 -04:00
|
|
|
FGeometryCacheMeshData* MeshData = nullptr;
|
2015-06-18 06:59:14 -04:00
|
|
|
|
|
|
|
|
// Retrieve the matrix/mesh data and the appropriate sample indices
|
|
|
|
|
Track->UpdateMatrixData(ElapsedTime + StartTimeOffset, bLooping, MatrixSampleIndex, WorldMatrix);
|
|
|
|
|
Track->UpdateMeshData(ElapsedTime + StartTimeOffset, bLooping, MeshSampleIndex, MeshData);
|
|
|
|
|
|
|
|
|
|
// First time so create rather than update the mesh sections
|
|
|
|
|
CreateTrackSection(TrackIndex, WorldMatrix, MeshData);
|
|
|
|
|
|
|
|
|
|
// Store the sample indices for both the mesh and matrix data
|
|
|
|
|
TrackMeshSampleIndices.Add(MeshSampleIndex);
|
|
|
|
|
TrackMatrixSampleIndices.Add(MatrixSampleIndex);
|
|
|
|
|
|
|
|
|
|
const float TrackMaxSampleTime = Track->GetMaxSampleTime();
|
2015-09-07 09:32:51 -04:00
|
|
|
Duration = (Duration > TrackMaxSampleTime) ? Duration : TrackMaxSampleTime;
|
2015-06-18 06:59:14 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::OnUnregister()
|
|
|
|
|
{
|
|
|
|
|
Super::OnUnregister();
|
|
|
|
|
|
|
|
|
|
NumTracks = 0;
|
|
|
|
|
TrackMatrixSampleIndices.Empty();
|
|
|
|
|
TrackMatrixSampleIndices.Empty();
|
|
|
|
|
TrackSections.Empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
|
|
|
|
|
{
|
|
|
|
|
SCOPE_CYCLE_COUNTER(STAT_GeometryCacheComponent_TickComponent);
|
|
|
|
|
if (GeometryCache && bRunning)
|
|
|
|
|
{
|
|
|
|
|
// Increase total elapsed time since BeginPlay according to PlayDirection and speed
|
|
|
|
|
ElapsedTime += (DeltaTime * PlayDirection * PlaybackSpeed);
|
|
|
|
|
|
|
|
|
|
if (ElapsedTime < 0.0f)
|
|
|
|
|
{
|
|
|
|
|
ElapsedTime += Duration;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int32 TrackIndex = 0; TrackIndex < NumTracks; ++TrackIndex)
|
|
|
|
|
{
|
|
|
|
|
// Determine if and which part of the section we have to update
|
|
|
|
|
UGeometryCacheTrack* Track = GeometryCache->Tracks[TrackIndex];
|
|
|
|
|
FMatrix WorldMatrix;
|
2015-09-07 09:32:51 -04:00
|
|
|
FGeometryCacheMeshData* MeshData = nullptr;
|
2015-06-18 06:59:14 -04:00
|
|
|
|
|
|
|
|
const bool bUpdateMatrix = Track->UpdateMatrixData(ElapsedTime + StartTimeOffset, bLooping, TrackMatrixSampleIndices[TrackIndex], WorldMatrix);
|
|
|
|
|
const bool bUpdateMesh = Track->UpdateMeshData(ElapsedTime + StartTimeOffset, bLooping, TrackMeshSampleIndices[TrackIndex], MeshData);
|
|
|
|
|
|
|
|
|
|
// Update sections according what is required
|
|
|
|
|
if (bUpdateMatrix)
|
|
|
|
|
{
|
|
|
|
|
UpdateTrackSectionMatrixData(TrackIndex, WorldMatrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bUpdateMesh)
|
|
|
|
|
{
|
|
|
|
|
UpdateTrackSectionMeshData(TrackIndex, MeshData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FBoxSphereBounds UGeometryCacheComponent::CalcBounds(const FTransform& LocalToWorld) const
|
|
|
|
|
{
|
|
|
|
|
return LocalBounds.TransformBy(LocalToWorld);
|
|
|
|
|
}
|
|
|
|
|
void UGeometryCacheComponent::UpdateLocalBounds()
|
|
|
|
|
{
|
|
|
|
|
FBox LocalBox(0);
|
|
|
|
|
|
|
|
|
|
for (const FTrackRenderData& Section : TrackSections)
|
|
|
|
|
{
|
|
|
|
|
// Use World matrix per section for correct bounding box
|
|
|
|
|
LocalBox += (Section.MeshData->BoundingBox.TransformBy(Section.WorldMatrix));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalBounds = LocalBox.IsValid ? FBoxSphereBounds(LocalBox) : FBoxSphereBounds(FVector(0, 0, 0), FVector(0, 0, 0), 0); // fallback to reset box sphere bounds
|
|
|
|
|
|
|
|
|
|
UpdateBounds();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FPrimitiveSceneProxy* UGeometryCacheComponent::CreateSceneProxy()
|
|
|
|
|
{
|
|
|
|
|
SceneProxy = new FGeometryCacheSceneProxy(this);
|
|
|
|
|
return SceneProxy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
|
|
|
|
{
|
|
|
|
|
InvalidateTrackSampleIndices();
|
|
|
|
|
MarkRenderStateDirty();
|
|
|
|
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 UGeometryCacheComponent::GetNumMaterials() const
|
|
|
|
|
{
|
|
|
|
|
// Sum the number of materials per track
|
|
|
|
|
int32 TotalNumMaterial = 0;
|
|
|
|
|
if ( GeometryCache )
|
|
|
|
|
{
|
|
|
|
|
for (UGeometryCacheTrack* Track : GeometryCache->Tracks)
|
|
|
|
|
{
|
|
|
|
|
TotalNumMaterial += Track->GetNumMaterials();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TotalNumMaterial;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::CreateTrackSection(int32 SectionIndex, const FMatrix& WorldMatrix, FGeometryCacheMeshData* MeshData)
|
|
|
|
|
{
|
|
|
|
|
// Ensure sections array is long enough
|
|
|
|
|
if (TrackSections.Num() <= SectionIndex)
|
|
|
|
|
{
|
|
|
|
|
TrackSections.SetNum(SectionIndex + 1, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reset this section (in case it already existed)
|
|
|
|
|
FTrackRenderData& NewSection = TrackSections[SectionIndex];
|
|
|
|
|
NewSection.Reset();
|
|
|
|
|
|
|
|
|
|
// Number of Vertices
|
|
|
|
|
const int32 NumVerts = MeshData->Vertices.Num();
|
2015-09-07 09:32:51 -04:00
|
|
|
|
2015-06-18 06:59:14 -04:00
|
|
|
// Store Matrix and MeshData-pointer
|
|
|
|
|
NewSection.WorldMatrix = WorldMatrix;
|
|
|
|
|
NewSection.MeshData = MeshData;
|
|
|
|
|
|
|
|
|
|
UpdateLocalBounds(); // Update overall bounds
|
|
|
|
|
MarkRenderStateDirty(); // Recreate scene proxy
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::UpdateTrackSectionMeshData(int32 SectionIndex, FGeometryCacheMeshData* MeshData)
|
|
|
|
|
{
|
|
|
|
|
// Check if the index is in range and Vertices contains any data
|
|
|
|
|
check(SectionIndex < TrackSections.Num() && MeshData != nullptr && "Invalid SectionIndex or Mesh Data");
|
|
|
|
|
// Reset this section (in case it already existed)
|
|
|
|
|
FTrackRenderData& UpdateSection = TrackSections[SectionIndex];
|
|
|
|
|
|
|
|
|
|
// Number of Vertices
|
|
|
|
|
const int32 NumVerts = MeshData->Vertices.Num();
|
2015-09-07 09:32:51 -04:00
|
|
|
|
2015-06-18 06:59:14 -04:00
|
|
|
// Update MeshDataPointer
|
|
|
|
|
UpdateSection.MeshData = MeshData;
|
|
|
|
|
|
2015-09-07 09:32:51 -04:00
|
|
|
//if (SceneProxy)
|
|
|
|
|
//{
|
|
|
|
|
// UpdateTrackSectionVertexbuffer(SectionIndex, MeshData);
|
|
|
|
|
// UpdateTrackSectionIndexbuffer(SectionIndex, MeshData->Indices);
|
|
|
|
|
// // Will update the bounds (used for frustum culling)
|
|
|
|
|
// MarkRenderTransformDirty();
|
|
|
|
|
// MarkRenderDynamicDataDirty();
|
|
|
|
|
//}
|
|
|
|
|
//else
|
|
|
|
|
//{
|
|
|
|
|
// // Recreate scene proxy
|
|
|
|
|
// MarkRenderStateDirty();
|
|
|
|
|
//}
|
2015-06-18 06:59:14 -04:00
|
|
|
|
|
|
|
|
// Update overall bounds
|
2015-09-07 09:32:51 -04:00
|
|
|
UpdateLocalBounds();
|
|
|
|
|
|
|
|
|
|
MarkRenderStateDirty();
|
2015-06-18 06:59:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::UpdateTrackSectionMatrixData(int32 SectionIndex, const FMatrix& WorldMatrix)
|
|
|
|
|
{
|
|
|
|
|
check(SectionIndex < TrackSections.Num() && "Invalid SectionIndex");
|
|
|
|
|
// Reset this section (in case it already existed)
|
|
|
|
|
FTrackRenderData& UpdateSection = TrackSections[SectionIndex];
|
|
|
|
|
|
|
|
|
|
// Update the WorldMatrix only
|
|
|
|
|
UpdateSection.WorldMatrix = WorldMatrix;
|
|
|
|
|
|
2015-09-07 09:32:51 -04:00
|
|
|
if (!IsRenderStateDirty() && SceneProxy != nullptr)
|
2015-06-18 06:59:14 -04:00
|
|
|
{
|
|
|
|
|
// Update it within the scene proxy
|
|
|
|
|
SceneProxy->UpdateSectionWorldMatrix(SectionIndex, WorldMatrix);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update local bounds
|
|
|
|
|
UpdateLocalBounds();
|
|
|
|
|
|
|
|
|
|
// Mark transform Dirty
|
|
|
|
|
MarkRenderTransformDirty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::UpdateTrackSectionVertexbuffer(int32 SectionIndex, FGeometryCacheMeshData* MeshData)
|
|
|
|
|
{
|
|
|
|
|
ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER(
|
|
|
|
|
FUpdateVertexBufferCommand,
|
|
|
|
|
FGeometryCacheSceneProxy*, SceneProxy, SceneProxy,
|
|
|
|
|
const int32, Index, SectionIndex,
|
|
|
|
|
FGeometryCacheMeshData*, Data, MeshData,
|
|
|
|
|
{
|
|
|
|
|
SceneProxy->UpdateSectionVertexBuffer(Index, Data);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-07 09:32:51 -04:00
|
|
|
void UGeometryCacheComponent::UpdateTrackSectionIndexbuffer(int32 SectionIndex, const TArray<uint32>& Indices)
|
2015-06-18 06:59:14 -04:00
|
|
|
{
|
|
|
|
|
ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER(
|
|
|
|
|
FUpdateVertexBufferCommand,
|
|
|
|
|
FGeometryCacheSceneProxy*, SceneProxy, SceneProxy,
|
|
|
|
|
const int32, Index, SectionIndex,
|
2015-09-07 09:32:51 -04:00
|
|
|
const TArray<uint32>&, Data, Indices,
|
2015-06-18 06:59:14 -04:00
|
|
|
{
|
|
|
|
|
SceneProxy->UpdateSectionIndexBuffer(Index, Data);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::OnObjectReimported(UGeometryCache* ImportedGeometryCache)
|
|
|
|
|
{
|
|
|
|
|
if (GeometryCache == ImportedGeometryCache)
|
|
|
|
|
{
|
|
|
|
|
ReleaseResources();
|
|
|
|
|
GeometryCache = ImportedGeometryCache;
|
|
|
|
|
|
2015-09-07 09:32:51 -04:00
|
|
|
if (GeometryCache != nullptr)
|
2015-06-18 06:59:14 -04:00
|
|
|
{
|
|
|
|
|
// Refresh NumTracks and clear Index Arrays
|
|
|
|
|
NumTracks = GeometryCache->Tracks.Num();
|
|
|
|
|
TrackMeshSampleIndices.Empty(GeometryCache->Tracks.Num());
|
|
|
|
|
TrackMatrixSampleIndices.Empty(GeometryCache->Tracks.Num());
|
|
|
|
|
|
|
|
|
|
Duration = 0.0f;
|
|
|
|
|
// Create mesh sections for each GeometryCacheTrack
|
|
|
|
|
for (int32 TrackIndex = 0; TrackIndex < NumTracks; ++TrackIndex)
|
|
|
|
|
{
|
|
|
|
|
UGeometryCacheTrack* Track = GeometryCache->Tracks[TrackIndex];
|
|
|
|
|
FMatrix WorldMatrix;
|
|
|
|
|
int32 MeshSampleIndex = -1;
|
|
|
|
|
int32 MatrixSampleIndex = -1;
|
2015-09-07 09:32:51 -04:00
|
|
|
FGeometryCacheMeshData* MeshData = nullptr;
|
2015-06-18 06:59:14 -04:00
|
|
|
|
|
|
|
|
// Retrieve the matrix/mesh data and the appropriate sample indices
|
|
|
|
|
Track->UpdateMatrixData(ElapsedTime + StartTimeOffset, bLooping, MatrixSampleIndex, WorldMatrix);
|
|
|
|
|
Track->UpdateMeshData(ElapsedTime + StartTimeOffset, bLooping, MeshSampleIndex, MeshData);
|
|
|
|
|
|
|
|
|
|
// First time so create rather than update the mesh sections
|
|
|
|
|
CreateTrackSection(TrackIndex, WorldMatrix, MeshData);
|
|
|
|
|
|
|
|
|
|
// Store the sample indices for both the mesh and matrix data
|
|
|
|
|
TrackMeshSampleIndices.Add(MeshSampleIndex);
|
|
|
|
|
TrackMatrixSampleIndices.Add(MatrixSampleIndex);
|
|
|
|
|
|
|
|
|
|
const float TrackMaxSampleTime = Track->GetMaxSampleTime();
|
|
|
|
|
Duration = (Duration > TrackMaxSampleTime) ? Duration : TrackMaxSampleTime;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SceneProxy)
|
|
|
|
|
{
|
|
|
|
|
SceneProxy->ClearSections();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MarkRenderStateDirty();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::Play()
|
|
|
|
|
{
|
|
|
|
|
bRunning = true;
|
|
|
|
|
PlayDirection = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::PlayFromStart()
|
|
|
|
|
{
|
|
|
|
|
ElapsedTime = 0.0f;
|
|
|
|
|
bRunning = true;
|
|
|
|
|
PlayDirection = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::Pause()
|
|
|
|
|
{
|
|
|
|
|
bRunning = !bRunning;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::Stop()
|
|
|
|
|
{
|
|
|
|
|
bRunning = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UGeometryCacheComponent::IsPlaying() const
|
|
|
|
|
{
|
|
|
|
|
return bRunning;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UGeometryCacheComponent::IsLooping() const
|
|
|
|
|
{
|
|
|
|
|
return bLooping;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::SetLooping(const bool bNewLooping)
|
|
|
|
|
{
|
|
|
|
|
bLooping = bNewLooping;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UGeometryCacheComponent::IsPlayingReversed() const
|
|
|
|
|
{
|
|
|
|
|
return FMath::IsNearlyEqual( PlayDirection, -1.0f );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float UGeometryCacheComponent::GetPlaybackSpeed() const
|
|
|
|
|
{
|
|
|
|
|
return PlaybackSpeed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::SetPlaybackSpeed(const float NewPlaybackSpeed)
|
|
|
|
|
{
|
|
|
|
|
// Currently only positive play back speeds are supported
|
|
|
|
|
PlaybackSpeed = fabs( NewPlaybackSpeed );
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-07 09:32:51 -04:00
|
|
|
bool UGeometryCacheComponent::SetGeometryCache(UGeometryCache* NewGeomCache)
|
|
|
|
|
{
|
|
|
|
|
// Do nothing if we are already using the supplied static mesh
|
|
|
|
|
if (NewGeomCache == GeometryCache)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't allow changing static meshes if "static" and registered
|
|
|
|
|
AActor* Owner = GetOwner();
|
|
|
|
|
if (!AreDynamicDataChangesAllowed() && Owner != nullptr)
|
|
|
|
|
{
|
|
|
|
|
FMessageLog("PIE").Warning(FText::Format(LOCTEXT("SetGeometryCache", "Calling SetGeometryCache on '{0}' but Mobility is Static."),
|
|
|
|
|
FText::FromString(GetPathName())));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GeometryCache = NewGeomCache;
|
|
|
|
|
|
|
|
|
|
ClearTrackData();
|
|
|
|
|
SetupTrackData();
|
|
|
|
|
|
|
|
|
|
// Need to send this to render thread at some point
|
|
|
|
|
MarkRenderStateDirty();
|
|
|
|
|
|
|
|
|
|
// Update physics representation right away
|
|
|
|
|
RecreatePhysicsState();
|
|
|
|
|
|
|
|
|
|
// Notify the streaming system. Don't use Update(), because this may be the first time the geometry cache has been set
|
|
|
|
|
// and the component may have to be added to the streaming system for the first time.
|
|
|
|
|
IStreamingManager::Get().NotifyPrimitiveAttached(this, DPT_Spawned);
|
|
|
|
|
|
|
|
|
|
// Since we have new tracks, we need to update bounds
|
|
|
|
|
UpdateBounds();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UGeometryCache* UGeometryCacheComponent::GetGeometryCache() const
|
|
|
|
|
{
|
|
|
|
|
return GeometryCache;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-18 06:59:14 -04:00
|
|
|
void UGeometryCacheComponent::PlayReversedFromEnd()
|
|
|
|
|
{
|
|
|
|
|
ElapsedTime = Duration;
|
|
|
|
|
PlayDirection = -1.0f;
|
|
|
|
|
bRunning = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::PlayReversed()
|
|
|
|
|
{
|
|
|
|
|
PlayDirection = -1.0f;
|
|
|
|
|
bRunning = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::InvalidateTrackSampleIndices()
|
|
|
|
|
{
|
|
|
|
|
for (int32& Index : TrackMeshSampleIndices)
|
|
|
|
|
{
|
|
|
|
|
Index = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int32& Index : TrackMatrixSampleIndices)
|
|
|
|
|
{
|
|
|
|
|
Index = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::ReleaseResources()
|
|
|
|
|
{
|
2015-09-07 09:32:51 -04:00
|
|
|
GeometryCache = nullptr;
|
2015-06-18 06:59:14 -04:00
|
|
|
NumTracks = 0;
|
|
|
|
|
TrackMatrixSampleIndices.Empty();
|
|
|
|
|
TrackMatrixSampleIndices.Empty();
|
|
|
|
|
TrackSections.Empty();
|
|
|
|
|
DetachFence.BeginFence();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::PreEditUndo()
|
|
|
|
|
{
|
|
|
|
|
InvalidateTrackSampleIndices();
|
|
|
|
|
MarkRenderStateDirty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UGeometryCacheComponent::PostEditUndo()
|
|
|
|
|
{
|
|
|
|
|
InvalidateTrackSampleIndices();
|
|
|
|
|
MarkRenderStateDirty();
|
|
|
|
|
}
|
2015-09-07 09:32:51 -04:00
|
|
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|