microsoft / MixedReality-UXTools-Unreal

UX tools and components for developing Mixed Reality applications in UE4.
https://microsoft.github.io/MixedReality-UXTools-Unreal/
MIT License
316 stars 86 forks source link

Issue - Scrolling Object Collection does not hide #59

Open shukenmg opened 2 years ago

shukenmg commented 2 years ago

I have a UxtScrollingObjectCollection under a UxtUIElementComponent and the Scroll Box won't hide when setting UxtUIElementComponent 's visibility to Hide.

luis-valverde-ms commented 2 years ago

Hi @shukenmg , can you share your setup? I'm assuming you have an actor with the UI Element and a child actor with the Scrolling Object Collection? What is the Scroll Box for you, the Back Plate component?

shukenmg commented 2 years ago

I'm assuming you have an actor with the UI Element and a child actor with the Scrolling Object Collection

Thats right, I then spawn (premade with custom code) UXT Button actors using the Spawn Actor node and then used the add actor to collection node to add them to the Scrolling box and then attach the button to the scrolling box component.

shukenmg commented 2 years ago

I made a temp workaround by modifying the ResetCollectionVisibility function to check if its parent UI Element component is hidden before Showing/Hiding the Actors:

void UUxtScrollingObjectCollection::ResetCollectionVisibility(bool IsInit)
{
    // Based on the current total offset of the collection we can determine which items are visible
    // within the viewable area. The offset is signed such that an offset below zero mean that the
    // first visible entry would have a negative index (if it existed), conversely a positive offset
    // means that entry 0 is off the front of the viewable area and we can see a section of entries
    // starting with  a later entry.
    // When calculating the first visible we should round down; similarly we should round up for the
    // last visible. Hence we can't rely on an implicit float to in cast.

    const AActor* Parent = GetOwner() ? GetOwner() : nullptr;

    bool IsParentVisible = true;
    if (Parent)
    {
        const UUxtUIElementComponent* ParentUIElement = Parent->FindComponentByClass<UUxtUIElementComponent>();

        if (ParentUIElement)
        {
            IsParentVisible = ParentUIElement->GetUIVisibilityInHierarchy() == EUxtUIElementVisibility::Show;
        }
    }

    const float CellDimension = GetSingleCellOffset();
    const int FirstVisibleRow = FMath::FloorToInt(GetCurrentNetOffset() / CellDimension);
    const int FirstNotVisibleRow = FMath::CeilToInt((GetCurrentNetOffset() / CellDimension) + ViewableArea);

    int FirstVisible = FMath::Max(FirstVisibleRow, 0) * Tiers;
    int FirstNotVisible = FMath::Max(FirstNotVisibleRow, 0) * Tiers;

    const TArray<AActor*>& Actors = GetAttachedActors();
    for (int i = 0; i < Actors.Num(); ++i)
    {
        const bool bHidden = IsParentVisible || IsInit ? (i < FirstVisible || i >= FirstNotVisible) : true;
        Actors[i]->SetActorHiddenInGame(bHidden);
        Actors[i]->SetActorTickEnabled(!bHidden);
        Actors[i]->SetActorEnableCollision(!bHidden);

#if WITH_EDITORONLY_DATA
        Actors[i]->SetIsTemporarilyHiddenInEditor(bHidden);
#endif // WITH_EDITORONLY_DATA
    }
}

bool IsInit

Is to ensure that the Scrolling Box is set up correctly since if some buttons are hidden during Init the bounds calculation breaks.

luis-valverde-ms commented 2 years ago

If that's working for you I'm going to leave work on this issue paused. We are on minimum maintenance mode for the time being and have to be selective about how we spend our limited resources. Eventually, I think the way forward is to make Scrolling Object Collection derive from UI Element. I'll leave this issue open to account for the need for that work.

shukenmg commented 2 years ago

Got it, thank you!