【目标】
植被工具-刷Actor
【思路】
1 添加类型FFoliageMeshInfo.AddInstance 的函数
2 添加Instance就直接SpawnActor
3 类结构
4 修改的函数
FEdModeFoliage.AddInstancesForBrush.
FEdModeFoliage.AddFoliageMesh
【步骤】
1 添加AcheType支持,添加FEdModeFoliage.AddFoliageAcheType
2 添加一个AActor的表,用于记录ArcheType
-
var const native Map_MirrorFoliageArcheTypes{TMap<classAActor*,structFFoliageMeshInfo>};
3 MFoliageEditWindow.OnDrop,资源拖到面板上
-
else { AActor*ArcheTypeActor=LoadObject<AActor>(NULL,*CurInfo.ObjectPathName, NULL, LOAD_None, NULL); if(ArcheTypeActor&&ArchetypeActor->HasAnyFlags(RF_ArchetypeObject)) { FoliageEditSystem->AddFoliageAcheType(ArcheTypeActor); FoliageMeshesProperty->NotifyChanged(); } }
-
for(TArray<FSelectedAssetInfo>::TConstIteratorDroppedAssetsIter(*(DroppedAssets.Get()));DroppedAssetsIter;++DroppedAssetsIter) { constFSelectedAssetInfo&CurInfo=*DroppedAssetsIter; if(CurInfo.ObjectClass!=UStaticMesh::StaticClass()&&CurInfo.ObjectClass!=AActor::StaticClass()) { Args->Effects=DragDropEffects::None; break; }





4 MFoliageEditWindow.OnDragOver 改成 IsChildOf 判断
-
voidOnDragOver(Object^Owner,DragEventArgs^Args) { Args->Effects=DragDropEffects::Copy; if(DroppedAssets.Get()!= NULL ) { for(TArray<FSelectedAssetInfo>::TConstIteratorDroppedAssetsIter(*(DroppedAssets.Get()));DroppedAssetsIter;++DroppedAssetsIter) { constFSelectedAssetInfo&CurInfo=*DroppedAssetsIter; if(CurInfo.ObjectClass!=UStaticMesh::StaticClass()&&!CurInfo.ObjectClass->IsChildOf(AActor::StaticClass())) { Args->Effects=DragDropEffects::None; break; } } } Args->Handled= TRUE; }
5 目前拖上去没有效果显示,
MFoliageMeshWrapper
列表和FEdModeFoliage.GetFoliageMeshList 绑定了,所以显示了FFoliageMeshUIInfo列表
6 添加FFoliageArcheTypeUIInfo 继承于FFoliageMeshUIInfo
-
1 structFFoliageResourceUIInfo:publicFFoliageMeshUIInfo 2 { 3 AActor*ArcheTypeActor; 4 FFoliageResourceUIInfo(UStaticMesh*InStaticMesh,AActor*InArcheTypeActor,FFoliageMeshInfo*InMeshInfo) 5 :FFoliageMeshUIInfo(InStaticMesh,InMeshInfo) 6 :ArcheTypeActor(InArcheTypeActor) 7 {} 8 };
7 FEdModeFoliage.GetFoliageMeshList 返回值
-
1 TArray<structFFoliageResourceUIInfo>&GetFoliageMeshList();
8 FEdModeFoliage.FoliageMeshList
-
// Placed level data TArray<structFFoliageResourceUIInfo>FoliageMeshList;
9
-
1 IMPLEMENT_COMPARE_CONSTREF(FFoliageResourceUIInfo,FoliageEdMode,{return A.MeshInfo->Settings->DisplayOrder- B.MeshInfo->Settings->DisplayOrder;});
10 FEdModeFoliage.UpdateFoliageMeshList
-
1 voidFEdModeFoliage::UpdateFoliageMeshList() 2 { 3 FoliageMeshList.Empty(); 4 AInstancedFoliageActor* IFA =AInstancedFoliageActor::GetInstancedFoliageActor(); 5 for(TMap<classUStaticMesh*,structFFoliageMeshInfo>::TIteratorMeshIt(IFA->FoliageMeshes);MeshIt;++MeshIt) 6 { 7 new(FoliageMeshList)FFoliageResourceUIInfo(MeshIt.Key(),NULL,&MeshIt.Value()); 8 } 9 for(TMap<classAActor*,structFFoliageMeshInfo>::TIteratorArcheTypeIt(IFA->FoliageArcheTypes);ArcheTypeIt;++ArcheTypeIt) 10 { 11 new(FoliageArcheTypeList)FFoliageResourceUIInfo(NULL,ArcheTypeIt.Key(),&ArcheTypeIt.Value()); 12 } 13 Sort<USE_COMPARE_CONSTREF(FFoliageResourceUIInfo,FoliageEdMode)>(&FoliageMeshList(0),FoliageMeshList.Num()); 14 }
11 MFoliageMeshWrapper 类构造需要用新类FFoliageResourceUIInfo
-
1 ref classMFoliageMeshWrapper:publicINotifyPropertyChanged 2 { 3 int index; 4 FFoliageResourceUIInfo& mesh; 5 UInstancedFoliageSettings* settings; 6 BitmapSource^ bitmap; 7 public: 8 virtual event PropertyChangedEventHandler^PropertyChanged; 9 MFoliageMeshWrapper( INT InIndex,FFoliageResourceUIInfo&InMesh) 10 : index(InIndex) 11 , mesh(InMesh) 12 , settings(mesh.MeshInfo->Settings) 13 { 14 if(mesh.StaticMesh) 15 bitmap =ThumbnailToolsCLR::GetBitmapSourceForObject(mesh.StaticMesh); 16 elseif(mesh.ArcheTypeActor) 17 bitmap =ThumbnailToolsCLR::GetBitmapSourceForObject(mesh.ArcheTypeActor); 18 }
12
-
typedefMEnumerableTArrayWrapper<MFoliageMeshWrapper,FFoliageResourceUIInfo>MFoliageMeshes;

13 跟FFoliageMeshUIInfo.StaticMesh 相关的修改
MFoliageMeshWrapper.StaticMeshName.get 获取名字的
-
1 propertyString^StaticMeshName{ 2 String^ get() 3 { 4 FStringName= mesh.StaticMesh? mesh.StaticMesh->GetName()? mesh.ArcheTypeActor->GetName(); 5 returnCLRTools::ToString(Name); 6 } 7 }
-
1 // Remove the current mesh 2 voidFoliageMeshRemoveButton_Click(Object^Owner,ExecutedRoutedEventArgs^Args) 3 { 4 MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter); 5 if(Mesh->GetStaticMesh()) 6 FoliageEditSystem->RemoveFoliageMesh(Mesh->GetStaticMesh()); 7 else 8 FoliageEditSystem->RemoveFoliageAcheType(Mesh->GetArcheTypeActor()); 9 FoliageMeshesProperty->NotifyChanged(); 10 }
添加MFoliageMeshWrapper.GetStaticMesh
AActor*GetStaticMesh(){return mesh.ArcheTypeActor;}
MFoliageEditWindow.FoliageMeshCopySettings_Click
-
voidFoliageMeshUseSettings_Click(Object^Owner,ExecutedRoutedEventArgs^Args) { GCallbackEvent->Send(CALLBACK_LoadSelectedAssetsIfNeeded); USelection*SelectedSet=GEditor->GetSelectedSet(UInstancedFoliageSettings::StaticClass()); UInstancedFoliageSettings*SelectedSettings=Cast<UInstancedFoliageSettings>(SelectedSet->GetTop(UInstancedFoliageSettings::StaticClass())); if(SelectedSettings!= NULL ) { MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter); if(Mesh->GetStaticMesh()) FoliageEditSystem->ReplaceSettingsObject(Mesh->GetStaticMesh(),SelectedSettings); else FoliageEditSystem->ReplaceSettingsObject(Mesh->GetArcheTypeActor(),SelectedSettings);
-
if(SelectedActor&&SelectedActor->HasAnyFlags(RF_ArchetypeObject)) { MFoliageMeshWrapper^Mesh= safe_cast<MFoliageMeshWrapper^>(Args->Parameter); FoliageEditSystem->ReplaceArchtypeActor(Mesh->GetArcheTypeActor(),SelectedActor); FoliageMeshesProperty->NotifyChanged(); }
13 FEdModeFoliage.ReplaceArchtypeActor
-
1 voidFEdModeFoliage::ReplaceArchtypeActor(AActor*OldArcheType,AActor*NewArcheType) 2 { 3 AInstancedFoliageActor* IFA =AInstancedFoliageActor::GetInstancedFoliageActor(); 4 FFoliageMeshInfo*OldMeshInfo= IFA->FoliageArcheTypes.Find(OldArcheType); 5 if(OldMeshInfo!= NULL &&OldArcheType!=NewArcheType&&NewArcheType->HasAnyFlags(RF_ArchetypeObject)) 6 { 7 INT InstancesNum=OldMeshInfo->Instances.Num()-OldMeshInfo->FreeInstanceIndices.Num(); 8 // Look for the new mesh in the mesh list, and either create a new mesh or merge the instances. 9 FFoliageMeshInfo*NewMeshInfo= IFA->FoliageArcheTypes.Find(NewArcheType); 10 if(NewMeshInfo== NULL ) 11 { 12 if(InstancesNum>0&& 13 appMsgf(AMT_YesNo,LocalizeSecure(LocalizeUnrealEd("FoliageMode_ReplaceMesh"),InstancesNum,*OldArcheType->GetName(),*NewArcheType->GetName()))!= ART_Yes ) 14 { 15 return; 16 } 17 GEditor->BeginTransaction(*LocalizeUnrealEd("FoliageMode_ChangeStaticMeshTransaction")); 18 IFA->Modify(); 19 NewMeshInfo= IFA->AddArcheType(NewArcheType); 20 NewMeshInfo->Settings->DisplayOrder=OldMeshInfo->Settings->DisplayOrder; 21 NewMeshInfo->Settings->ShowNothing=OldMeshInfo->Settings->ShowNothing; 22 NewMeshInfo->Settings->ShowPaintSettings=OldMeshInfo->Settings->ShowPaintSettings; 23 NewMeshInfo->Settings->ShowInstanceSettings=OldMeshInfo->Settings->ShowInstanceSettings; 24 } 25 else 26 if(InstancesNum>0&& 27 appMsgf(AMT_YesNo,LocalizeSecure(LocalizeUnrealEd("FoliageMode_ReplaceMeshMerge"),InstancesNum,*OldArcheType->GetName(),*NewArcheType->GetName()))!= ART_Yes ) 28 { 29 return; 30 } 31 else 32 { 33 GEditor->BeginTransaction(*LocalizeUnrealEd("FoliageMode_ChangeStaticMeshTransaction")); 34 IFA->Modify(); 35 } 36 if(InstancesNum>0) 37 { 38 // copy instances from old to new. 39 for( INT Idx=0;Idx<OldMeshInfo->Instances.Num();Idx++) 40 { 41 if(OldMeshInfo->Instances(Idx).ClusterIndex!=-1) 42 { 43 NewMeshInfo->AddInstanceAT( IFA,NewArcheType,OldMeshInfo->Instances(Idx)); 44 } 45 } 46 } 47 // Remove the old mesh. 48 IFA->RemoveArcheType(OldArcheType); 49 GEditor->EndTransaction(); 50 // Update mesh list. 51 UpdateFoliageMeshList(); 52 } 53 }
14 添加FFoliageMeshInfo.AddInstanceAT
-
1 voidFFoliageMeshInfo::AddInstanceAT(classAInstancedFoliageActor*InIFA,classAActor*InActor,constFFoliageInstance&InNewInstance) 2 { 3 }
目前是刷不上Actor模型吗,主要是FEdModeFoliage.ApplyBrush 函数里没有处理
15 修改FEdModeFoliage.ApplyBrush
-
1 // ArcheType 2 for(TMap<classAActor*,structFFoliageMeshInfo>::TIteratorArcheTypeIt(IFA->FoliageArcheTypes);ArcheTypeIt;++ArcheTypeIt) 3 { 4 FFoliageMeshInfo&MeshInfo=ArcheTypeIt.Value(); 5 UInstancedFoliageSettings*MeshSettings=MeshInfo.Settings; 6 if(MeshSettings->IsSelected) 7 { 8 // Find the instances already in the area. 9 TArray<INT>Instances; 10 FSphereBrushSphere(BrushLocation,UISettings.GetRadius()); 11 MeshInfo.GetInstancesInsideSphere(BrushSphere,Instances); 12 if(UISettings.GetLassoSelectToolSelected()) 13 { 14 // Shift unpaints 15 MeshInfo.SelectInstances( IFA,!IsShiftDown(ViewportClient->Viewport),Instances); 16 } 17 else 18 if(UISettings.GetReapplyToolSelected()) 19 { 20 if(MeshSettings->ReapplyDensity) 21 { 22 // Adjust instance density 23 FMeshInfoSnapshot*SnapShot=InstanceATSnapshot.Find(ArcheTypeIt.Key()); 24 if(SnapShot) 25 { 26 // Use snapshot to determine number of instances at the start of the brush stroke 27 INT NewInstanceCount= appRound((FLOAT)SnapShot->CountInstancesInsideSphere(BrushSphere)*MeshSettings->ReapplyDensityAmount); 28 if(MeshSettings->ReapplyDensityAmount>1.f&&NewInstanceCount>Instances.Num()) 29 { 30 AddInstancesATForBrush( IFA,ArcheTypeIt.Key(),MeshInfo,NewInstanceCount,Instances,Pressure); 31 } 32 else 33 if(MeshSettings->ReapplyDensityAmount<1.f&&NewInstanceCount<Instances.Num()) 34 { 35 RemoveInstancesForBrush( IFA,MeshInfo,NewInstanceCount,Instances,Pressure); 36 } 37 } 38 } 39 // Reapply any settings checked by the user 40 ReapplyInstancesForBrush( IFA,MeshInfo,Instances); 41 } 42 else 43 if(UISettings.GetPaintToolSelected()) 44 { 45 // Shift unpaints 46 if(IsShiftDown(ViewportClient->Viewport)) 47 { 48 INT DesiredInstanceCount= appRound(BrushArea*MeshSettings->Density*UISettings.GetUnpaintDensity()/(1000.f*1000.f)); 49 if(DesiredInstanceCount<Instances.Num()) 50 { 51 RemoveInstancesForBrush( IFA,MeshInfo,DesiredInstanceCount,Instances,Pressure); 52 } 53 } 54 else 55 { 56 // This is the total set of instances disregarding parameters like slope, height or layer. 57 FLOAT DesiredInstanceCountFloat=BrushArea*MeshSettings->Density*UISettings.GetPaintDensity()/(1000.f*1000.f); 58 // Allow a single instance with a random chance, if the brush is smaller than the density 59 INT DesiredInstanceCount=DesiredInstanceCountFloat>1.f? appRound(DesiredInstanceCountFloat): appFrand()<DesiredInstanceCountFloat?1:0; 60 AddInstancesATForBrush( IFA,ArcheTypeIt.Key(),MeshInfo,DesiredInstanceCount,Instances,Pressure); 61 } 62 } 63 } 64 }
16 添加Instance的函数FEdModeFoliage.AddInstancesATForBrush
-
1 /** Add instances inside the brush to match DesiredInstanceCount */ 2 voidFEdModeFoliage::AddInstancesATForBrush(AInstancedFoliageActor* IFA,AActor*AchetypeActor,FFoliageMeshInfo&MeshInfo, INT DesiredInstanceCount,TArray<INT>&ExistingInstances, FLOAT Pressure) 3 { 4 UInstancedFoliageSettings*MeshSettings=MeshInfo.Settings; 5 if(DesiredInstanceCount>ExistingInstances.Num()) 6 { 7 INT ExistingInstanceBuckets[NUM_INSTANCE_BUCKETS]; 8 appMemzero(ExistingInstanceBuckets,sizeof(ExistingInstanceBuckets)); 9 // Cache store mapping between component and weight data 10 TMap<ULandscapeComponent*,TArray<BYTE>>*LandscapeLayerCache= NULL; 11 FNameLandscapeLayerName=MeshSettings->LandscapeLayer; 12 if(LandscapeLayerName!= NAME_None ) 13 { 14 LandscapeLayerCache=&LandscapeLayerCaches.FindOrAdd(LandscapeLayerName); 15 // Find the landscape weights of existing ExistingInstances 16 for( INT Idx=0;Idx<ExistingInstances.Num();Idx++) 17 { 18 FFoliageInstance&Instance=MeshInfo.Instances(ExistingInstances(Idx)); 19 ULandscapeHeightfieldCollisionComponent*HitLandscapeCollision=Cast<ULandscapeHeightfieldCollisionComponent>(Instance.Base); 20 if(HitLandscapeCollision) 21 { 22 ULandscapeComponent*HitLandscape=HitLandscapeCollision->GetLandscapeComponent(); 23 if(HitLandscape) 24 { 25 TArray<BYTE>*LayerCache=&LandscapeLayerCache->FindOrAdd(HitLandscape); 26 FLOAT HitWeight=HitLandscape->GetLayerWeightAtLocation(Instance.Location,LandscapeLayerName,LayerCache); 27 // Add count to bucket. 28 ExistingInstanceBuckets[appRound(HitWeight*(FLOAT)(NUM_INSTANCE_BUCKETS-1))]++; 29 } 30 } 31 } 32 } 33 else 34 { 35 // When not tied to a layer, put all the ExistingInstances in the last bucket. 36 ExistingInstanceBuckets[NUM_INSTANCE_BUCKETS-1]=ExistingInstances.Num(); 37 } 38 // We calculate a set of potential ExistingInstances for the brush area. 39 TArray<FPotentialInstance>PotentialInstanceBuckets[NUM_INSTANCE_BUCKETS]; 40 appMemzero(PotentialInstanceBuckets,sizeof(PotentialInstanceBuckets)); 41 // Quick lookup of potential instance locations, used for overlapping check. 42 TArray<FVector>PotentialInstanceLocations; 43 FFoliageInstanceHashPotentialInstanceHash(7);// use 128x128 cell size, as the brush radius is typically small. 44 PotentialInstanceLocations.Empty(DesiredInstanceCount); 45 // Radius where we expect to have a single instance, given the density rules 46 const FLOAT DensityCheckRadius=Max<FLOAT>( appSqrt((1000.f*1000.f)/(PI *MeshSettings->Density)),MeshSettings->Radius); 47 for( INT DesiredIdx=0;DesiredIdx<DesiredInstanceCount;DesiredIdx++) 48 { 49 FVectorStart,End; 50 GetRandomVectorInBrush(Start,End); 51 FCheckResultHit; 52 if(!GWorld->SingleLineCheck(Hit, NULL,End,Start, TRACE_World | TRACE_Level,FVector(0.f,0.f,0.f), NULL)) 53 { 54 // Check filters 55 if((Hit.Component&& 56 (Hit.Component->GetOutermost()!=GWorld->CurrentLevel->GetOutermost()|| 57 (!UISettings.bFilterLandscape &&Hit.Component->IsA(ULandscapeHeightfieldCollisionComponent::StaticClass()))|| 58 (!UISettings.bFilterStaticMesh &&Hit.Component->IsA(UStaticMeshComponent::StaticClass()))|| 59 (!UISettings.bFilterTerrain &&Hit.Component->IsA(UTerrainComponent::StaticClass()))))|| 60 (Hit.Actor&&Hit.Actor->IsA(AWorldInfo::StaticClass())&&(!UISettings.bFilterBSP ||GWorld->Levels(Hit.LevelIndex)!=GWorld->CurrentLevel))) 61 { 62 continue; 63 } 64 if(!CheckLocationForPotentialInstance(MeshInfo,MeshSettings,DensityCheckRadius,Hit.Location,Hit.Normal,PotentialInstanceLocations,PotentialInstanceHash)) 65 { 66 continue; 67 } 68 // Check landscape layer 69 FLOAT HitWeight=1.f; 70 if(LandscapeLayerName!= NAME_None ) 71 { 72 ULandscapeHeightfieldCollisionComponent*HitLandscapeCollision=Cast<ULandscapeHeightfieldCollisionComponent>(Hit.Component); 73 if(HitLandscapeCollision) 74 { 75 ULandscapeComponent*HitLandscape=HitLandscapeCollision->GetLandscapeComponent(); 76 if(HitLandscape) 77 { 78 TArray<BYTE>*LayerCache=&LandscapeLayerCache->FindOrAdd(HitLandscape); 79 HitWeight=HitLandscape->GetLayerWeightAtLocation(Hit.Location,LandscapeLayerName,LayerCache); 80 // Reject instance randomly in proportion to weight 81 if(HitWeight<= appFrand()) 82 { 83 continue; 84 } 85 } 86 } 87 } 88 new(PotentialInstanceBuckets[appRound(HitWeight*(FLOAT)(NUM_INSTANCE_BUCKETS-1))])FPotentialInstance(Hit.Location,Hit.Normal,Hit.Component,HitWeight); 89 } 90 } 91 for( INT BucketIdx=0;BucketIdx< NUM_INSTANCE_BUCKETS;BucketIdx++) 92 { 93 TArray<FPotentialInstance>&PotentialInstances=PotentialInstanceBuckets[BucketIdx]; 94 FLOAT BucketFraction=(FLOAT)(BucketIdx+1)/(FLOAT)NUM_INSTANCE_BUCKETS; 95 // We use the number that actually succeeded in placement (due to parameters) as the target 96 // for the number that should be in the brush region. 97 INT AdditionalInstances=Clamp<INT>( appRound(BucketFraction*(FLOAT)(PotentialInstances.Num()-ExistingInstanceBuckets[BucketIdx])*Pressure),0,PotentialInstances.Num()); 98 for( INT Idx=0;Idx<AdditionalInstances;Idx++) 99 { 100 FFoliageInstanceInst=PotentialInstances(Idx).PlaceInstance(MeshSettings); 101 MeshInfo.AddInstanceAT( IFA,AchetypeActor,Inst); 102 } 103 } 104 } 105 }
-
1 structFFoliageInstanceCluster 2 { 3 UInstancedStaticMeshComponent*ClusterComponent; 4 TArray<AActor*>ActorInstances; 5 FFoliageInstanceCluster.GetInstanceCount 6 INT GetInstanceCount() 7 { 8 INT TotalCount=0; 9 if(ClusterComponent) 10 TotalCount+=ClusterComponent->PerInstanceSMData.Num(); 11 TotalCount+=ActorInstances.Num(); 12 }
18 添加FFoliageMeshInfo.AddInstanceAT
-
1 voidFFoliageMeshInfo::AddInstanceAT(classAInstancedFoliageActor*InIFA,classAActor*InArchetypeActor,constFFoliageInstance&InNewInstance) 2 { 3 InIFA->Modify(); 4 // Add the instance taking either a free slot or adding a new item. 5 INT InstanceIndex=FreeInstanceIndices.Num()>0?FreeInstanceIndices.Pop():Instances.Add(); 6 FFoliageInstance&AddedInstance=Instances(InstanceIndex); 7 AddedInstance=InNewInstance; 8 // Add the instance to the hash 9 InstanceHash->InsertInstance(InNewInstance.Location,InstanceIndex); 10 FFoliageComponentHashInfo&ComponentHashInfo=ComponentHash.FindOrAddKey(InNewInstance.Base); 11 ComponentHashInfo.Instances.Add(InstanceIndex); 12 // Find the best cluster to allocate the instance to. 13 FFoliageInstanceCluster*BestCluster= NULL; 14 INT BestClusterIndex= INDEX_NONE; 15 FLOAT BestClusterDistSq= FLT_MAX; 16 INT MaxInstancesPerCluster=Settings->MaxInstancesPerCluster; 17 FLOAT MaxClusterRadiusSq=Square(Settings->MaxClusterRadius); 18 for( INT ClusterIdx=0;ClusterIdx<InstanceClusters.Num();ClusterIdx++) 19 { 20 FFoliageInstanceCluster&Cluster=InstanceClusters(ClusterIdx); 21 if(Cluster.InstanceIndices.Num()<MaxInstancesPerCluster) 22 { 23 FLOAT DistSq=(Cluster.Bounds.Origin-InNewInstance.Location).SizeSquared(); 24 if(DistSq<BestClusterDistSq&&DistSq<MaxClusterRadiusSq) 25 { 26 BestCluster=&Cluster; 27 BestClusterIndex=ClusterIdx; 28 BestClusterDistSq=DistSq; 29 } 30 } 31 } 32 // Calculate transform for the instance 33 FMatrixInstanceTransform=InNewInstance.GetInstanceTransform(); 34 if(BestCluster== NULL ) 35 { 36 BestClusterIndex=InstanceClusters.Num(); 37 BestCluster=new(InstanceClusters)FFoliageInstanceCluster( 38 NULL, 39 FBoxSphereBounds()// LWF_TODO 40 ); 41 //ApplyInstancedFoliageSettings( BestCluster->ClusterComponent ); 42 } 43 else 44 { 45 // BestCluster->ClusterComponent->Modify(); 46 // BestCluster->ClusterComponent->InvalidateLightingCache(); 47 // BestCluster->Bounds = BestCluster->Bounds + InMesh->Bounds.TransformBy(InstanceTransform); 48 } 49 BestCluster->InstanceIndices.AddItem(InstanceIndex); 50 // Save the cluster index 51 AddedInstance.ClusterIndex=BestClusterIndex; 52 // Add the instance to the ActorList 53 AActor* pActor =GWorld->SpawnActor(InArchetypeActor->GetClass(), NAME_None,InNewInstance.Location,InNewInstance.Rotation,InArchetypeActor);// Spawn Actor 54 BestCluster->ActorInstances.AddItem(pActor); 55 // FInstancedStaticMeshInstanceData* NewInstanceData = new(BestCluster->ClusterComponent->PerInstanceSMData) FInstancedStaticMeshInstanceData(); 56 if(BestCluster->ClusterComponent->SelectedInstances.Num()>0) 57 { 58 BestCluster->ClusterComponent->SelectedInstances.AddItem(FALSE); 59 } 60 // NewInstanceData->Transform = InstanceTransform; 61 // NewInstanceData->LightmapUVBias = FVector2D( -1.0f, -1.0f ); 62 // NewInstanceData->ShadowmapUVBias = FVector2D( -1.0f, -1.0f ); 63 // BestCluster->ClusterComponent->bNeedsReattach = TRUE; 64 #if _DEBUG 65 CheckValid(); 66 #endif 67 InIFA->ConditionalUpdateComponents(); 68 }
18 修改所有FFoliageInstanceCluster.ClusterComponent 的地方
太多地方了
FFoliageMeshInfo.CheckValid
终于能刷出东西来了