EVisibility SBlueprintEditorSelectedDebugObjectWidget::IsSelectDebugObjectButtonVisible() const { check(GetBlueprintObj()); if (UObject* DebugObj = GetBlueprintObj()->GetObjectBeingDebugged()) { if (AActor* Actor = Cast<AActor>(DebugObj)) { return EVisibility::Visible; } } return EVisibility::Collapsed; }
TSharedPtr<FString> SBlueprintEditorSelectedDebugObjectWidget::GetDebugWorldName() const { check(GetBlueprintObj()); check(DebugWorlds.Num() == DebugWorldNames.Num()); if (UObject* DebugObj = GetBlueprintObj()->GetObjectBeingDebugged()) { for (int32 WorldIdx = 0; WorldIdx < DebugWorlds.Num(); ++WorldIdx) { if (DebugObj->IsIn(DebugWorlds[WorldIdx].Get())) { return DebugWorldNames[WorldIdx]; } } } return DebugWorldNames[0]; }
TSharedPtr<FString> SBlueprintEditorSelectedDebugObjectWidget::GetDebugObjectName() const { check(GetBlueprintObj()); check(DebugObjects.Num() == DebugObjectNames.Num()); if (UObject* DebugObj = GetBlueprintObj()->GetObjectBeingDebugged()) { for (int32 ObjectIndex = 0; ObjectIndex < DebugObjects.Num(); ++ObjectIndex) { if (DebugObjects[ObjectIndex].IsValid() && (DebugObjects[ObjectIndex].Get() == DebugObj)) { return DebugObjectNames[ObjectIndex]; } } } return DebugObjectNames[0]; }
void SBlueprintEditorSelectedDebugObjectWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) { if (GetBlueprintObj()) { if (UObject* Object = GetBlueprintObj()->GetObjectBeingDebugged()) { if (Object != LastObjectObserved.Get()) { LastObjectObserved = Object; GenerateDebugObjectNames(false); TSharedPtr<FString> NewSelection; for (int32 Index = 0; Index < DebugObjects.Num(); ++Index) { if (DebugObjects[Index] == Object) { NewSelection = DebugObjectNames[Index]; break; } } if (!NewSelection.IsValid()) { NewSelection = DebugObjectNames[0]; } DebugObjectsComboBox->SetSelectedItem(NewSelection); } } else { LastObjectObserved = NULL; // If the object name is a name (rather than the 'No debug selected' string then regenerate the names (which will reset the combo box) as the object is invalid. TSharedPtr<FString> CurrentString = DebugObjectsComboBox->GetSelectedItem(); if (*CurrentString != GetNoDebugString()) { GenerateDebugObjectNames(false); } } } }
FGraphAppearanceInfo FWidgetBlueprintEditor::GetGraphAppearance(UEdGraph* InGraph) const { FGraphAppearanceInfo AppearanceInfo = FBlueprintEditor::GetGraphAppearance(InGraph); if ( GetBlueprintObj()->IsA(UWidgetBlueprint::StaticClass()) ) { AppearanceInfo.CornerText = LOCTEXT("AppearanceCornerText", "WIDGET BLUEPRINT"); } return AppearanceInfo; }
void FSCSEditorViewportClient::BeginTransaction(const FText& Description) { //UE_LOG(LogSCSEditorViewport, Log, TEXT("FSCSEditorViewportClient::BeginTransaction() pre: %s %08x"), SessionName, *((uint32*)&ScopedTransaction)); if(!ScopedTransaction) { ScopedTransaction = new FScopedTransaction(Description); auto BlueprintEditor = BlueprintEditorPtr.Pin(); if (BlueprintEditor.IsValid()) { UBlueprint* PreviewBlueprint = BlueprintEditor->GetBlueprintObj(); if (PreviewBlueprint != nullptr) { FBlueprintEditorUtils::MarkBlueprintAsModified(PreviewBlueprint); } TArray<FSCSEditorTreeNodePtrType> SelectedNodes = BlueprintEditor->GetSelectedSCSEditorTreeNodes(); for(auto SelectedSCSNodeIter(SelectedNodes.CreateIterator()); SelectedSCSNodeIter; ++SelectedSCSNodeIter) { FSCSEditorTreeNodePtrType Node = *SelectedSCSNodeIter; if(Node.IsValid()) { if(USCS_Node* SCS_Node = Node->GetSCSNode()) { SCS_Node->Modify(); } // Modify both the component template and the instance in the preview actor (provided there is one) UActorComponent* ComponentTemplate = Node->GetEditableComponentTemplate(PreviewBlueprint); if (ComponentTemplate != nullptr) { ComponentTemplate->SetFlags(RF_Transactional); ComponentTemplate->Modify(); } AActor* PreviewActor = GetPreviewActor(); if (PreviewActor) { UActorComponent* ComponentPreviewInstance = Node->FindComponentInstanceInActor(PreviewActor); if (ComponentPreviewInstance != nullptr) { ComponentPreviewInstance->SetFlags(RF_Transactional); ComponentPreviewInstance->Modify(); } } } } } } //UE_LOG(LogSCSEditorViewport, Log, TEXT("FSCSEditorViewportClient::BeginTransaction() post: %s %08x"), SessionName, *((uint32*)&ScopedTransaction)); }
void SBlueprintEditorSelectedDebugObjectWidget::SelectedDebugObject_OnClicked() { if (UObject* DebugObj = GetBlueprintObj()->GetObjectBeingDebugged()) { if (AActor* Actor = Cast<AActor>(DebugObj)) { GEditor->SelectNone(false, true, false); GEditor->SelectActor(Actor, true, true, true); GUnrealEd->Exec(Actor->GetWorld(), TEXT("CAMERA ALIGN ACTIVEVIEWPORTONLY")); } } }
void SBlueprintEditorSelectedDebugObjectWidget::DebugObjectSelectionChanged(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo) { check(DebugObjects.Num() == DebugObjectNames.Num()); for (int32 ObjectIndex = 0; ObjectIndex < DebugObjectNames.Num(); ++ObjectIndex) { if (*DebugObjectNames[ObjectIndex] == *NewSelection) { UObject* DebugObj = DebugObjects[ObjectIndex].IsValid() ? DebugObjects[ObjectIndex].Get() : NULL; GetBlueprintObj()->SetObjectBeingDebugged(DebugObj); } } }
void SBlueprintEditorSelectedDebugObjectWidget::OnRefresh() { if (GetBlueprintObj()) { GenerateDebugWorldNames(false); if (UObject* Object = GetBlueprintObj()->GetObjectBeingDebugged()) { GenerateDebugObjectNames(false); if (AActor* Actor = Cast<AActor>(Object)) { DebugObjectsComboBox->SetSelectedItem(MakeShareable(new FString(Actor->GetActorLabel()))); } else { DebugObjectsComboBox->SetSelectedItem(MakeShareable(new FString(Object->GetName()))); } } else { // If we didnt find and object its probably a good idea to regenerate the names now - this will also ensure the combo box has a valid selection. GenerateDebugObjectNames(false); } } }
void SBlueprintEditorSelectedDebugObjectWidget::DebugWorldSelectionChanged(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo) { if (!NewSelection.IsValid()) { return; } check(DebugObjects.Num() == DebugObjectNames.Num()); for (int32 WorldIdx = 0; WorldIdx < DebugWorldNames.Num(); ++WorldIdx) { if (*DebugWorldNames[WorldIdx] == *NewSelection) { GetBlueprintObj()->SetWorldBeingDebugged(DebugWorlds[WorldIdx].Get()); GenerateDebugObjectNames(false); } } }
UScriptBlueprint* FScriptBlueprintEditor::GetScriptBlueprintObj() const { return Cast<UScriptBlueprint>(GetBlueprintObj()); }
bool FSCSEditorViewportClient::InputWidgetDelta( FViewport* Viewport, EAxisList::Type CurrentAxis, FVector& Drag, FRotator& Rot, FVector& Scale ) { bool bHandled = false; if(bIsManipulating && CurrentAxis != EAxisList::None) { bHandled = true; AActor* PreviewActor = GetPreviewActor(); auto BlueprintEditor = BlueprintEditorPtr.Pin(); if (PreviewActor && BlueprintEditor.IsValid()) { TArray<FSCSEditorTreeNodePtrType> SelectedNodes = BlueprintEditor->GetSelectedSCSEditorTreeNodes(); if(SelectedNodes.Num() > 0) { FVector ModifiedScale = Scale; if( GEditor->UsePercentageBasedScaling() ) { ModifiedScale = Scale * ((GEditor->GetScaleGridSize() / 100.0f) / GEditor->GetGridSize()); } TSet<USceneComponent*> UpdatedComponents; for(auto It(SelectedNodes.CreateIterator());It;++It) { FSCSEditorTreeNodePtrType SelectedNodePtr = *It; // Don't allow editing of a root node, inherited SCS node or child node that also has a movable (non-root) parent node selected const bool bCanEdit = !SelectedNodePtr->IsRootComponent() && !SelectedNodePtr->IsInherited() && !IsMovableParentNodeSelected(SelectedNodePtr, SelectedNodes); if(bCanEdit) { USceneComponent* SceneComp = Cast<USceneComponent>(SelectedNodePtr->FindComponentInstanceInActor(PreviewActor)); USceneComponent* SelectedTemplate = Cast<USceneComponent>(SelectedNodePtr->GetEditableComponentTemplate(BlueprintEditor->GetBlueprintObj())); if(SceneComp != NULL && SelectedTemplate != NULL) { // Cache the current default values for propagation FVector OldRelativeLocation = SelectedTemplate->RelativeLocation; FRotator OldRelativeRotation = SelectedTemplate->RelativeRotation; FVector OldRelativeScale3D = SelectedTemplate->RelativeScale3D; // Adjust the deltas as necessary FComponentEditorUtils::AdjustComponentDelta(SceneComp, Drag, Rot); TSharedPtr<ISCSEditorCustomization> Customization = BlueprintEditor->CustomizeSCSEditor(SceneComp); if(Customization.IsValid() && Customization->HandleViewportDrag(SceneComp, SelectedTemplate, Drag, Rot, ModifiedScale, GetWidgetLocation())) { UpdatedComponents.Add(SceneComp); UpdatedComponents.Add(SelectedTemplate); } else { // Apply delta to the preview actor's scene component GEditor->ApplyDeltaToComponent( SceneComp, true, &Drag, &Rot, &ModifiedScale, SceneComp->RelativeLocation ); UpdatedComponents.Add(SceneComp); // Apply delta to the template component object GEditor->ApplyDeltaToComponent( SelectedTemplate, true, &Drag, &Rot, &ModifiedScale, SelectedTemplate->RelativeLocation ); UpdatedComponents.Add(SelectedTemplate); } UBlueprint* PreviewBlueprint = UBlueprint::GetBlueprintFromClass(PreviewActor->GetClass()); if(PreviewBlueprint != NULL) { // Like PostEditMove(), but we only need to re-run construction scripts if(PreviewBlueprint && PreviewBlueprint->bRunConstructionScriptOnDrag) { PreviewActor->RerunConstructionScripts(); } SceneComp->PostEditComponentMove(true); // @TODO HACK passing 'finished' every frame... // If a constraint, copy back updated constraint frames to template UPhysicsConstraintComponent* ConstraintComp = Cast<UPhysicsConstraintComponent>(SceneComp); UPhysicsConstraintComponent* TemplateComp = Cast<UPhysicsConstraintComponent>(SelectedTemplate); if(ConstraintComp && TemplateComp) { TemplateComp->ConstraintInstance.CopyConstraintGeometryFrom(&ConstraintComp->ConstraintInstance); } // Iterate over all the active archetype instances and propagate the change(s) to the matching component instance TArray<UObject*> ArchetypeInstances; if(SelectedTemplate->HasAnyFlags(RF_ArchetypeObject)) { SelectedTemplate->GetArchetypeInstances(ArchetypeInstances); for(int32 InstanceIndex = 0; InstanceIndex < ArchetypeInstances.Num(); ++InstanceIndex) { SceneComp = Cast<USceneComponent>(ArchetypeInstances[InstanceIndex]); if(SceneComp && SceneComp->GetOwner() != PreviewActor) { FComponentEditorUtils::ApplyDefaultValueChange(SceneComp, SceneComp->RelativeLocation, OldRelativeLocation, SelectedTemplate->RelativeLocation); FComponentEditorUtils::ApplyDefaultValueChange(SceneComp, SceneComp->RelativeRotation, OldRelativeRotation, SelectedTemplate->RelativeRotation); FComponentEditorUtils::ApplyDefaultValueChange(SceneComp, SceneComp->RelativeScale3D, OldRelativeScale3D, SelectedTemplate->RelativeScale3D); } } } else if(UObject* Outer = SelectedTemplate->GetOuter()) { Outer->GetArchetypeInstances(ArchetypeInstances); for(int32 InstanceIndex = 0; InstanceIndex < ArchetypeInstances.Num(); ++InstanceIndex) { if(ArchetypeInstances[InstanceIndex] != PreviewActor) { SceneComp = static_cast<USceneComponent*>(FindObjectWithOuter(ArchetypeInstances[InstanceIndex], SelectedTemplate->GetClass(), SelectedTemplate->GetFName())); if(SceneComp) { FComponentEditorUtils::ApplyDefaultValueChange(SceneComp, SceneComp->RelativeLocation, OldRelativeLocation, SelectedTemplate->RelativeLocation); FComponentEditorUtils::ApplyDefaultValueChange(SceneComp, SceneComp->RelativeRotation, OldRelativeRotation, SelectedTemplate->RelativeRotation); FComponentEditorUtils::ApplyDefaultValueChange(SceneComp, SceneComp->RelativeScale3D, OldRelativeScale3D, SelectedTemplate->RelativeScale3D); } } } } } } } } GUnrealEd->RedrawLevelEditingViewports(); } } Invalidate(); } return bHandled; }
EVisibility SBlueprintEditorSelectedDebugObjectWidget::ShouldShowDebugObjectPicker() const { check(GetBlueprintObj()); return FBlueprintEditorUtils::IsLevelScriptBlueprint(GetBlueprintObj()) ? EVisibility::Collapsed : EVisibility::Visible; }
void SBlueprintEditorSelectedDebugObjectWidget::GenerateDebugObjectNames(bool bRestoreSelection) { TSharedPtr<FString> OldSelection; // Store off the old selection if (bRestoreSelection && DebugObjectsComboBox.IsValid()) { OldSelection = DebugObjectsComboBox->GetSelectedItem(); } // Empty the lists of actors and regenerate them DebugObjects.Empty(); DebugObjectNames.Empty(); DebugObjects.Add(NULL); DebugObjectNames.Add(MakeShareable(new FString(GetNoDebugString()))); // Grab custom objects that should always be visible, regardless of the world TArray<FCustomDebugObject> CustomDebugObjects; BlueprintEditor.Pin()->GetCustomDebugObjects(/*inout*/ CustomDebugObjects); for (const FCustomDebugObject& Entry : CustomDebugObjects) { if (Entry.NameOverride.IsEmpty()) { AddDebugObject(Entry.Object); } else { AddDebugObjectWithName(Entry.Object, Entry.NameOverride); } } // Check for a specific debug world. If DebugWorld=NULL we take that as "any PIE world" UWorld* DebugWorld = NULL; if (DebugWorldsComboBox.IsValid()) { TSharedPtr<FString> CurrentWorldSelection = DebugWorldsComboBox->GetSelectedItem(); int32 SelectedIndex = DebugWorldNames.Find(CurrentWorldSelection); if (SelectedIndex > 0 && DebugWorldNames.IsValidIndex(SelectedIndex)) { DebugWorld = DebugWorlds[SelectedIndex].Get(); } } UWorld* PreviewWorld = NULL; TSharedPtr<SSCSEditorViewport> PreviewViewportPtr = BlueprintEditor.Pin()->GetSCSViewport(); if (PreviewViewportPtr.IsValid()) { PreviewWorld = PreviewViewportPtr->GetPreviewScene().GetWorld(); } for (TObjectIterator<UObject> It; It; ++It) { UObject* TestObject = *It; // Skip Blueprint preview objects (don't allow them to be selected for debugging) if (PreviewWorld != NULL && TestObject->IsIn(PreviewWorld)) { continue; } const bool bPassesFlags = !TestObject->HasAnyFlags(RF_PendingKill | RF_ClassDefaultObject); const bool bGeneratedByBlueprint = TestObject->GetClass()->ClassGeneratedBy == GetBlueprintObj(); if (bPassesFlags && bGeneratedByBlueprint) { UObject *ObjOuter = TestObject; UWorld *ObjWorld = NULL; while (ObjWorld == NULL && ObjOuter != NULL) { ObjOuter = ObjOuter->GetOuter(); ObjWorld = Cast<UWorld>(ObjOuter); } // Object not in any world if (!ObjWorld) { continue; } // Make check on owning level (not streaming level) if (ObjWorld->PersistentLevel && ObjWorld->PersistentLevel->OwningWorld) { ObjWorld = ObjWorld->PersistentLevel->OwningWorld; } // We have a specific debug world and the object isnt in it if (DebugWorld && ObjWorld != DebugWorld) { continue; } // We don't have a specific debug world, but the object isnt in a PIE world if (ObjWorld->WorldType != EWorldType::PIE) { continue; } AddDebugObject(TestObject); } } // Attempt to restore the old selection if (bRestoreSelection && DebugObjectsComboBox.IsValid()) { bool bMatchFound = false; for (int32 ObjectIndex = 0; ObjectIndex < DebugObjectNames.Num(); ++ObjectIndex) { if (*DebugObjectNames[ObjectIndex] == *OldSelection) { DebugObjectsComboBox->SetSelectedItem(DebugObjectNames[ObjectIndex]); bMatchFound = true; break; } } // No match found, use the default option if (!bMatchFound) { DebugObjectsComboBox->SetSelectedItem(DebugObjectNames[0]); } } // Finally ensure we have a valid selection if (DebugObjectsComboBox.IsValid()) { TSharedPtr<FString> CurrentSelection = DebugObjectsComboBox->GetSelectedItem(); if (DebugObjectNames.Find(CurrentSelection) == INDEX_NONE) { if (DebugObjectNames.Num() > 0) { DebugObjectsComboBox->SetSelectedItem(DebugObjectNames[0]); } else { DebugObjectsComboBox->ClearSelection(); } } DebugObjectsComboBox->RefreshOptions(); } }
UWidgetBlueprint* FWidgetBlueprintEditor::GetWidgetBlueprintObj() const { return Cast<UWidgetBlueprint>(GetBlueprintObj()); }