Skip to content

FIXME: AActorSingleton::TryBecomeNewInstanceOrSelfDestroy WITH_EDITOR behavior #2

@sleeptightAnsiC

Description

@sleeptightAnsiC

I shall at least try to refactor this someday:

#if WITH_EDITOR
/* In case of placing an Actor in the Level Viewport, we canNOT simply Destroy it.
* Instead, we must "tell" the Editor to delete it, which will fire some additional clean up logic.
* Also we're showing a message to the Editor user telling what is happening, so we can avoid confusion.
*
* FIXME: Current implementation is fine but has few caveats:
* 1. it "touches" the Level despite that no actual changes have been done
* 2. if user uses 'undo' after deletion, the duplicate object will be restored
* 3. if user's Actor does something after being placed, we won't be able to revert it
* These are pretty bad... I should probably find another way to achieve the same goal.
*
* TODO: Possible solutions for the issues listed above:
* 1. Prevent Actor from being placed into the Level in the first place
* I have no idea if this can be achieved with Unreal Engine...
* If that's possible, then there is probably some kind of Interface in AActor that allows it
* but otherwise I have no clue where to look for solution
* 2. Instead of deletion, we can simply use Editor's 'undo' feature
* The problem with this one is that we would never know for sure how many times call the 'undo'
* because Actor, when placed, can do some other stuff around which adds up to the undo/redo buffer.
* We would need to find out how many times we need to call the 'undo'
* However, this option seems the most promising and possible to implement :)
*/
if (ThisWorld->IsEditorWorld() && !ThisWorld->IsPlayInEditor())
{
/* Show Dialogue Message */
const FText MessageTitle = this->GetMessageTitle();
const FText MessageBody = this->GetMessageBody();
FMessageDialog::Debugf(MessageBody, MessageTitle);
/* Delete 'this' via UEditorActorSubsystem */
auto* EditorActorSubsystem = GEditor->GetEditorSubsystem<UEditorActorSubsystem>();
check(EditorActorSubsystem)
EditorActorSubsystem->ClearActorSelectionSet();
EditorActorSubsystem->SetActorSelectionState(this, true);
EditorActorSubsystem->DeleteSelectedActors(ThisWorld);
GEngine->ForceGarbageCollection(true);
/* Garbage Actor still seems to be selected in the Details Panel despite already being destroyed.
* 'UEditorActorSubsystem::DeleteSelectedActors' doesn't handle this by itself,
* so we are clearing the Actor selection on the very next tick which fixes this issue. */
ThisWorld->GetTimerManager().SetTimerForNextTick(
[&]()->void
{
EditorActorSubsystem->SelectNothing();
}
);
return;
}
#endif //WITH_EDITOR

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions