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 | ||
| 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 | ||||
| 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 |