void UAnimGraphNode_TwoBoneIK::DrawTargetLocation(FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* SkelComp, USkeleton * Skeleton, EBoneControlSpace SpaceBase, FName SpaceBoneName, const FVector & TargetLocation, const FColor & TargetColor, const FColor & BoneColor) const { const bool bInBoneSpace = (SpaceBase == BCS_ParentBoneSpace) || (SpaceBase == BCS_BoneSpace); const int32 SpaceBoneIndex = bInBoneSpace ? Skeleton->GetReferenceSkeleton().FindBoneIndex(SpaceBoneName) : INDEX_NONE; // Transform EffectorLocation from EffectorLocationSpace to ComponentSpace. FTransform TargetTransform = FTransform (TargetLocation); FTransform CSTransform; ConvertToComponentSpaceTransform(SkelComp, TargetTransform, CSTransform, SpaceBoneIndex, SpaceBase); FTransform WorldTransform = CSTransform * SkelComp->ComponentToWorld; #if 0 // @TODO : remove this code because this doesn't show correct target location DrawCoordinateSystem( PDI, WorldTransform.GetLocation(), WorldTransform.GetRotation().Rotator(), 20.f, SDPG_Foreground ); DrawWireDiamond( PDI, WorldTransform.ToMatrixWithScale(), 2.f, TargetColor, SDPG_Foreground ); #endif if (bInBoneSpace) { ConvertToComponentSpaceTransform(SkelComp, FTransform::Identity, CSTransform, SpaceBoneIndex, SpaceBase); WorldTransform = CSTransform * SkelComp->ComponentToWorld; DrawCoordinateSystem( PDI, WorldTransform.GetLocation(), WorldTransform.GetRotation().Rotator(), 20.f, SDPG_Foreground ); DrawWireDiamond( PDI, WorldTransform.ToMatrixWithScale(), 2.f, BoneColor, SDPG_Foreground ); } }
void FSocketEditingHelper::DrawSockets(FSpriteGeometryEditMode* GeometryEditMode, UPrimitiveComponent* PreviewComponent, const FSceneView* View, FPrimitiveDrawInterface* PDI) { if (PreviewComponent != nullptr) { const bool bIsHitTesting = PDI->IsHitTesting(); const float DiamondSize = 5.0f; const FColor UnselectedDiamondColor(255, 128, 128); const FColor SelectedDiamondColor(FColor::White); TArray<FComponentSocketDescription> SocketList; PreviewComponent->QuerySupportedSockets(/*out*/ SocketList); for (const FComponentSocketDescription& Socket : SocketList) { if (bIsHitTesting) { TSharedPtr<FSpriteSelectedSocket> Data = MakeShareable(new FSpriteSelectedSocket); Data->PreviewComponentPtr = PreviewComponent; Data->SocketName = Socket.Name; PDI->SetHitProxy(new HSpriteSelectableObjectHitProxy(Data)); } const bool bIsSelected = (GeometryEditMode != nullptr) && GeometryEditMode->IsSocketSelected(Socket.Name); const FColor& DiamondColor = bIsSelected ? SelectedDiamondColor : UnselectedDiamondColor; const FMatrix SocketTM = PreviewComponent->GetSocketTransform(Socket.Name, RTS_World).ToMatrixWithScale(); DrawWireDiamond(PDI, SocketTM, DiamondSize, DiamondColor, SDPG_Foreground); if (bIsHitTesting) { PDI->SetHitProxy(nullptr); } } } }
void FStaticMeshEditorViewportClient::Draw(const FSceneView* View,FPrimitiveDrawInterface* PDI) { FEditorViewportClient::Draw(View, PDI); if (bShowCollision && StaticMesh->BodySetup) { const FColor SelectedColor(149, 223, 157); const FColor UnselectedColor(157, 149, 223); // Draw bodies FKAggregateGeom* AggGeom = &StaticMesh->BodySetup->AggGeom; for (int32 i = 0; i < AggGeom->SphereElems.Num(); ++i) { HSMECollisionProxy* HitProxy = new HSMECollisionProxy(KPT_Sphere, i); PDI->SetHitProxy(HitProxy); const FColor CollisionColor = StaticMeshEditorPtr.Pin()->IsSelectedPrim(HitProxy->PrimData) ? SelectedColor : UnselectedColor; const FKSphereElem& SphereElem = AggGeom->SphereElems[i]; const FTransform ElemTM = SphereElem.GetTransform(); SphereElem.DrawElemWire(PDI, ElemTM, 1.f, CollisionColor); PDI->SetHitProxy(NULL); } for (int32 i = 0; i < AggGeom->BoxElems.Num(); ++i) { HSMECollisionProxy* HitProxy = new HSMECollisionProxy(KPT_Box, i); PDI->SetHitProxy(HitProxy); const FColor CollisionColor = StaticMeshEditorPtr.Pin()->IsSelectedPrim(HitProxy->PrimData) ? SelectedColor : UnselectedColor; const FKBoxElem& BoxElem = AggGeom->BoxElems[i]; const FTransform ElemTM = BoxElem.GetTransform(); BoxElem.DrawElemWire(PDI, ElemTM, 1.f, CollisionColor); PDI->SetHitProxy(NULL); } for (int32 i = 0; i < AggGeom->SphylElems.Num(); ++i) { HSMECollisionProxy* HitProxy = new HSMECollisionProxy(KPT_Sphyl, i); PDI->SetHitProxy(HitProxy); const FColor CollisionColor = StaticMeshEditorPtr.Pin()->IsSelectedPrim(HitProxy->PrimData) ? SelectedColor : UnselectedColor; const FKSphylElem& SphylElem = AggGeom->SphylElems[i]; const FTransform ElemTM = SphylElem.GetTransform(); SphylElem.DrawElemWire(PDI, ElemTM, 1.f, CollisionColor); PDI->SetHitProxy(NULL); } for (int32 i = 0; i < AggGeom->ConvexElems.Num(); ++i) { HSMECollisionProxy* HitProxy = new HSMECollisionProxy(KPT_Convex, i); PDI->SetHitProxy(HitProxy); const FColor CollisionColor = StaticMeshEditorPtr.Pin()->IsSelectedPrim(HitProxy->PrimData) ? SelectedColor : UnselectedColor; const FKConvexElem& ConvexElem = AggGeom->ConvexElems[i]; const FTransform ElemTM = ConvexElem.GetTransform(); ConvexElem.DrawElemWire(PDI, ElemTM, CollisionColor); PDI->SetHitProxy(NULL); } } if( bShowSockets ) { const FColor SocketColor = FColor(255, 128, 128); for(int32 i=0; i < StaticMesh->Sockets.Num(); i++) { UStaticMeshSocket* Socket = StaticMesh->Sockets[i]; if(Socket) { FMatrix SocketTM; Socket->GetSocketMatrix(SocketTM, StaticMeshComponent); PDI->SetHitProxy( new HSMESocketProxy(i) ); DrawWireDiamond(PDI, SocketTM, 5.f, SocketColor, SDPG_Foreground); PDI->SetHitProxy( NULL ); } } } // Draw any edges that are currently selected by the user if( SelectedEdgeIndices.Num() > 0 ) { for(int32 VertexIndex = 0; VertexIndex < SelectedEdgeVertices.Num(); VertexIndex += 2) { FVector EdgeVertices[ 2 ]; EdgeVertices[ 0 ] = SelectedEdgeVertices[VertexIndex]; EdgeVertices[ 1 ] = SelectedEdgeVertices[VertexIndex + 1]; PDI->DrawLine( StaticMeshComponent->ComponentToWorld.TransformPosition( EdgeVertices[ 0 ] ), StaticMeshComponent->ComponentToWorld.TransformPosition( EdgeVertices[ 1 ] ), FColor( 255, 255, 0 ), SDPG_World ); } } if( bDrawNormals || bDrawTangents || bDrawBinormals ) { FStaticMeshLODResources& LODModel = StaticMesh->RenderData->LODResources[StaticMeshEditorPtr.Pin()->GetCurrentLODIndex()]; FIndexArrayView Indices = LODModel.IndexBuffer.GetArrayView(); uint32 NumIndices = Indices.Num(); FMatrix LocalToWorldInverseTranspose = StaticMeshComponent->ComponentToWorld.ToMatrixWithScale().InverseFast().GetTransposed(); for (uint32 i = 0; i < NumIndices; i++) { const FVector& VertexPos = LODModel.PositionVertexBuffer.VertexPosition( Indices[i] ); const FVector WorldPos = StaticMeshComponent->ComponentToWorld.TransformPosition( VertexPos ); const FVector& Normal = LODModel.VertexBuffer.VertexTangentZ( Indices[i] ); const FVector& Binormal = LODModel.VertexBuffer.VertexTangentY( Indices[i] ); const FVector& Tangent = LODModel.VertexBuffer.VertexTangentX( Indices[i] ); const float Len = 5.0f; if( bDrawNormals ) { PDI->DrawLine( WorldPos, WorldPos+LocalToWorldInverseTranspose.TransformVector( Normal ).SafeNormal() * Len, FLinearColor( 0.0f, 1.0f, 0.0f), SDPG_World ); } if( bDrawTangents ) { PDI->DrawLine( WorldPos, WorldPos+LocalToWorldInverseTranspose.TransformVector( Tangent ).SafeNormal() * Len, FLinearColor( 1.0f, 0.0f, 0.0f), SDPG_World ); } if( bDrawBinormals ) { PDI->DrawLine( WorldPos, WorldPos+LocalToWorldInverseTranspose.TransformVector( Binormal ).SafeNormal() * Len, FLinearColor( 0.0f, 0.0f, 1.0f), SDPG_World ); } } } if( bShowPivot ) { FUnrealEdUtils::DrawWidget(View, PDI, StaticMeshComponent->ComponentToWorld.ToMatrixWithScale(), 0, 0, EAxisList::All, EWidgetMovementMode::WMM_Translate, false); } if( bDrawAdditionalData ) { const TArray<UAssetUserData*>* UserDataArray = StaticMesh->GetAssetUserDataArray(); if (UserDataArray != NULL) { for (int32 AdditionalDataIndex = 0; AdditionalDataIndex < UserDataArray->Num(); ++AdditionalDataIndex) { if ((*UserDataArray)[AdditionalDataIndex] != NULL) { (*UserDataArray)[AdditionalDataIndex]->Draw(PDI, View); } } } } }
void FEdMode::Render(const FSceneView* View,FViewport* Viewport,FPrimitiveDrawInterface* PDI) { // Let the current mode tool render if it wants to FModeTool* tool = GetCurrentTool(); if( tool ) { tool->Render( View, Viewport, PDI ); } if(UsesPropertyWidgets()) { bool bHitTesting = PDI->IsHitTesting(); AActor* SelectedActor = GetFirstSelectedActorInstance(); if (SelectedActor != NULL) { UClass* Class = SelectedActor->GetClass(); TArray<FPropertyWidgetInfo> WidgetInfos; GetPropertyWidgetInfos(Class, SelectedActor, WidgetInfos); FEditorScriptExecutionGuard ScriptGuard; for(int32 i=0; i<WidgetInfos.Num(); i++) { FString WidgetName = WidgetInfos[i].PropertyName; FName WidgetValidator = WidgetInfos[i].PropertyValidationName; int32 WidgetIndex = WidgetInfos[i].PropertyIndex; bool bIsTransform = WidgetInfos[i].bIsTransform; bool bSelected = (WidgetName == EditedPropertyName) && (WidgetIndex == EditedPropertyIndex); FColor WidgetColor = bSelected ? FColor::White : FColor(128, 128, 255); FVector LocalPos = FVector::ZeroVector; if(bIsTransform) { FTransform LocalTM = GetPropertyValueByName<FTransform>(SelectedActor, WidgetName, WidgetIndex); LocalPos = LocalTM.GetLocation(); } else { LocalPos = GetPropertyValueByName<FVector>(SelectedActor, WidgetName, WidgetIndex); } FTransform ActorToWorld = SelectedActor->ActorToWorld(); FVector WorldPos = ActorToWorld.TransformPosition(LocalPos); UFunction* ValidateFunc= NULL; if(WidgetValidator != NAME_None && (ValidateFunc = SelectedActor->FindFunction(WidgetValidator)) != NULL) { FString ReturnText; SelectedActor->ProcessEvent(ValidateFunc, &ReturnText); //if we have a negative result, the widget color is red. WidgetColor = ReturnText.IsEmpty() ? WidgetColor : FColor::Red; } FTranslationMatrix WidgetTM(WorldPos); const float WidgetSize = 0.035f; const float ZoomFactor = FMath::Min<float>(View->ViewMatrices.ProjMatrix.M[0][0], View->ViewMatrices.ProjMatrix.M[1][1]); const float WidgetRadius = View->Project(WorldPos).W * (WidgetSize / ZoomFactor); if(bHitTesting) PDI->SetHitProxy( new HPropertyWidgetProxy(WidgetName, WidgetIndex, bIsTransform) ); DrawWireDiamond(PDI, WidgetTM, WidgetRadius, WidgetColor, SDPG_Foreground ); if(bHitTesting) PDI->SetHitProxy( NULL ); } } } }