View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002634 | NoesisGUI | Unreal | public | 2023-06-28 12:43 | 2023-09-26 20:30 |
Reporter | ThisIsMyUserName | Assigned To | sfernandez | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | 3.2.1 | ||||
Target Version | 3.2.2 | Fixed in Version | 3.2.2 | ||
Summary | 0002634: StoryboardCompletedTrigger is invoked for all items in list | ||||
Description | When Storyboard is played for item in list, the StoryboardCompletedTrigger is invoked for all items in list. Noesis Forum post - https://www.noesisengine.com/forums/viewtopic.php?t=2976 | ||||
Steps To Reproduce | Using Noesis 3.2.1 and Unreal Engine Create a DataTemplate that contains a Storyboard and StoryboardCompletedTrigger. Create a list of DataTemplate items (at least 2 items) Play the Storyboard on 1 item Observe StoryboardCompletedTrigger function being called on every item in the list | ||||
Tags | C++, Unreal | ||||
Platform | Any | ||||
related to | 0002653 | resolved | sfernandez | ControlStoryboardAction inside ControlTemplates only works for one instance |
related to | 0002052 | resolved | sfernandez | Storyboard Completed event triggered for all instances of a template |
Could you please try the attahed patch, it should fix your problem. StoryboardCompletedTrigger.patch (8,694 bytes)
Index: Include/NsApp/ControlStoryboardAction.h =================================================================== --- Include/NsApp/ControlStoryboardAction.h (revision 12571) +++ Include/NsApp/ControlStoryboardAction.h (working copy) @@ -14,6 +14,12 @@ #include <NsApp/StoryboardAction.h> +namespace Noesis +{ +class FrameworkElement; +class Storyboard; +} + namespace NoesisApp { @@ -68,6 +74,10 @@ void SetControlStoryboardOption(ControlStoryboardOption option); //@} + /// Returns the element that is used as target to play the storyboard + static Noesis::FrameworkElement* FindStoryboardTarget(Noesis::Storyboard* storyboard, + Noesis::DependencyObject* associatedObject); + public: static const Noesis::DependencyProperty* ControlStoryboardOptionProperty; Index: Include/NsApp/StoryboardCompletedTrigger.h =================================================================== --- Include/NsApp/StoryboardCompletedTrigger.h (revision 12571) +++ Include/NsApp/StoryboardCompletedTrigger.h (working copy) @@ -15,6 +15,7 @@ namespace Noesis { +class FrameworkElement; struct TimelineEventArgs; } @@ -64,6 +65,7 @@ /// From AttachableObject //@{ + void OnAttached() override; void OnDetaching() override; //@} @@ -75,6 +77,9 @@ private: void OnStoryboardCompleted(Noesis::BaseComponent* sender, const Noesis::TimelineEventArgs& e); +private: + Noesis::FrameworkElement* mTarget; + NS_DECLARE_REFLECTION(StoryboardCompletedTrigger, StoryboardTrigger) }; Index: Src/ControlStoryboardAction.cpp =================================================================== --- Src/ControlStoryboardAction.cpp (revision 12571) +++ Src/ControlStoryboardAction.cpp (working copy) @@ -9,6 +9,7 @@ #include <NsGui/Storyboard.h> #include <NsGui/ResourceDictionary.h> #include <NsGui/FrameworkElement.h> +#include <NsGui/FrameworkTemplate.h> #include <NsCore/ReflectionImplement.h> #include <NsCore/ReflectionImplementEnum.h> @@ -60,6 +61,32 @@ } //////////////////////////////////////////////////////////////////////////////////////////////////// +Noesis::FrameworkElement* ControlStoryboardAction::FindStoryboardTarget( + Noesis::Storyboard* storyboard, Noesis::DependencyObject* associatedObject) +{ + Noesis::IUITreeNode* node = storyboard->GetNodeParent(); + + // For Storyboards defined in the Template Resources always use the associated object + Noesis::ResourceDictionary* resources = Noesis::DynamicCast<Noesis::ResourceDictionary*>(node); + if (resources != 0 && + Noesis::DynamicCast<Noesis::FrameworkTemplate*>(resources->GetNodeParent()) != 0) + { + return Noesis::FindTreeElement(Noesis::DynamicCast<Noesis::IUITreeNode*>(associatedObject)); + } + + // Next try with the scope where Storyboard was defined + Noesis::FrameworkElement* target = Noesis::FindTreeElement(node); + if (target != 0 && target->IsConnectedToView()) + { + return target; + } + + // In case Storyboard was defined in Application resources or the Resources of a + // template element, we next try with the scope of the associated object + return Noesis::FindTreeElement(Noesis::DynamicCast<Noesis::IUITreeNode*>(associatedObject)); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// void ControlStoryboardAction::Invoke(BaseComponent*) { Noesis::Storyboard* storyboard = GetStoryboard(); @@ -66,14 +93,7 @@ DependencyObject* associatedObject = GetAssociatedObject(); if (associatedObject != 0 && storyboard != 0) { - // First try with the scope where Storyboard was defined as target - Noesis::FrameworkElement* target = FindTreeElement(storyboard->GetNodeParent()); - if (target == 0 || !target->IsConnectedToView()) - { - // In case Storyboard was defined in Application resources or the Resources of a - // template element, we next try with the scope of the associated object as target - target = Noesis::FindTreeElement(Noesis::DynamicCast<IUITreeNode*>(associatedObject)); - } + Noesis::FrameworkElement* target = FindStoryboardTarget(storyboard, associatedObject); // Execute the Storyboard action if we have a valid target connected to the UI tree if (target != 0 && target->IsConnectedToView()) @@ -83,7 +103,7 @@ case ControlStoryboardOption_Play: { Noesis::IUITreeNode* node = Noesis::DynamicCast<IUITreeNode*>(associatedObject); - Noesis::FrameworkElement* ns = FindTreeElement(node); + Noesis::FrameworkElement* ns = Noesis::FindTreeElement(node); storyboard->Begin(target, ns, true); break; } @@ -105,7 +125,7 @@ else { Noesis::IUITreeNode* node = Noesis::DynamicCast<IUITreeNode*>(associatedObject); - Noesis::FrameworkElement* ns = FindTreeElement(node); + Noesis::FrameworkElement* ns = Noesis::FindTreeElement(node); storyboard->Begin(target, ns, true); } break; Index: Src/StoryboardCompletedTrigger.cpp =================================================================== --- Src/StoryboardCompletedTrigger.cpp (revision 12571) +++ Src/StoryboardCompletedTrigger.cpp (working copy) @@ -5,7 +5,9 @@ #include <NsApp/StoryboardCompletedTrigger.h> +#include <NsApp/ControlStoryboardAction.h> #include <NsGui/Storyboard.h> +#include <NsGui/FrameworkElement.h> #include <NsGui/ResourceDictionary.h> #include <NsCore/ReflectionImplementEmpty.h> @@ -14,7 +16,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// -StoryboardCompletedTrigger::StoryboardCompletedTrigger() +StoryboardCompletedTrigger::StoryboardCompletedTrigger(): mTarget(0) { } @@ -57,6 +59,17 @@ } //////////////////////////////////////////////////////////////////////////////////////////////////// +void StoryboardCompletedTrigger::OnAttached() +{ + Noesis::Storyboard* storyboard = GetStoryboard(); + if (storyboard != 0) + { + Noesis::DependencyObject* associatedObject = GetAssociatedObject(); + mTarget = ControlStoryboardAction::FindStoryboardTarget(storyboard, associatedObject); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// void StoryboardCompletedTrigger::OnDetaching() { Noesis::Storyboard* storyboard = GetStoryboard(); @@ -64,11 +77,14 @@ { storyboard->Completed() -= MakeDelegate(this, &StoryboardCompletedTrigger::OnStoryboardCompleted); + + mTarget = 0; } } //////////////////////////////////////////////////////////////////////////////////////////////////// -void StoryboardCompletedTrigger::OnStoryboardChanged(const Noesis::DependencyPropertyChangedEventArgs& e) +void StoryboardCompletedTrigger::OnStoryboardChanged( + const Noesis::DependencyPropertyChangedEventArgs& e) { Noesis::Storyboard* oldStoryboard = e.OldValue<Noesis::Ptr<Noesis::Storyboard>>(); Noesis::Storyboard* newStoryboard = e.NewValue<Noesis::Ptr<Noesis::Storyboard>>(); @@ -77,18 +93,27 @@ { oldStoryboard->Completed() -= MakeDelegate(this, &StoryboardCompletedTrigger::OnStoryboardCompleted); + + mTarget = 0; } if (newStoryboard != 0) { newStoryboard->Completed() += MakeDelegate(this, &StoryboardCompletedTrigger::OnStoryboardCompleted); + + Noesis::DependencyObject* associatedObject = GetAssociatedObject(); + mTarget = ControlStoryboardAction::FindStoryboardTarget(newStoryboard, associatedObject); } } //////////////////////////////////////////////////////////////////////////////////////////////////// -void StoryboardCompletedTrigger::OnStoryboardCompleted(BaseComponent*, const Noesis::TimelineEventArgs&) +void StoryboardCompletedTrigger::OnStoryboardCompleted(BaseComponent*, + const Noesis::TimelineEventArgs& e) { - InvokeActions(0); + if (e.target == mTarget) + { + InvokeActions(0); + } } //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2023-06-28 12:43 | ThisIsMyUserName | New Issue | |
2023-06-28 12:43 | ThisIsMyUserName | Tag Attached: C++ | |
2023-06-28 12:43 | ThisIsMyUserName | Tag Attached: Unreal | |
2023-06-28 12:48 | sfernandez | Assigned To | => sfernandez |
2023-06-28 12:48 | sfernandez | Status | new => assigned |
2023-06-28 12:48 | sfernandez | Product Version | 3.2 => 3.2.1 |
2023-06-28 12:48 | sfernandez | Target Version | => 3.2.2 |
2023-06-29 12:35 | sfernandez | Note Added: 0008572 | |
2023-06-29 12:35 | sfernandez | File Added: StoryboardCompletedTrigger.patch | |
2023-06-29 12:35 | sfernandez | Status | assigned => feedback |
2023-07-24 13:00 | sfernandez | Relationship added | related to 0002653 |
2023-07-24 13:01 | sfernandez | Relationship added | related to 0002052 |
2023-09-26 20:30 | sfernandez | Status | feedback => resolved |
2023-09-26 20:30 | sfernandez | Resolution | open => fixed |
2023-09-26 20:30 | sfernandez | Fixed in Version | => 3.2.2 |