2 * Copyright(c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using global::System.Runtime.InteropServices;
20 using System.ComponentModel;
21 using System.Collections.Generic;
22 using System.Globalization;
24 namespace Tizen.NUI.BaseComponents
27 /// LottieAnimationView renders an animated vector image (Lottie file).
29 /// <since_tizen> 7 </since_tizen>
30 public partial class LottieAnimationView : ImageView
32 #region Constructor, Destructor, Dispose
34 /// LottieAnimationView constructor
36 /// <param name="scale">The factor of scaling image, default : 1.0f</param>
37 /// <param name="shown">false : not displayed (hidden), true : displayed (shown), default : true</param>
39 /// If the shown parameter is false, the animation is not visible even if the LottieAnimationView instance is created.
43 /// LottieAnimationView myLottie = new LottieAnimationView();
44 /// LottieAnimationView myLottie2 = new LottieAnimationView(2.0f);
45 /// LottieAnimationView myLottie3 = new LottieAnimationView(1.0f, false);
48 /// <since_tizen> 7 </since_tizen>
49 public LottieAnimationView(float scale = 1.0f, bool shown = true) : base()
51 ActionPlay = Interop.LottieAnimationView.AnimatedVectorImageVisualActionPlayGet();
52 ActionPause = Interop.LottieAnimationView.AnimatedVectorImageVisualActionPauseGet();
53 ActionStop = Interop.LottieAnimationView.AnimatedVectorImageVisualActionStopGet();
55 NUILog.Debug($"< constructor GetId={GetId()} >");
56 currentStates.url = "";
57 currentStates.frame = -1;
58 currentStates.loopCount = 1;
59 currentStates.loopMode = LoopingModeType.Restart;
60 currentStates.stopEndAction = StopBehaviorType.CurrentFrame;
61 currentStates.framePlayRangeMin = -1;
62 currentStates.framePlayRangeMax = -1;
63 currentStates.changed = false;
64 currentStates.totalFrame = -1;
65 currentStates.scale = scale;
66 currentStates.redrawInScalingDown = true;
71 /// Dispose(DisposeTypes type)
73 /// <param name="type"></param>
74 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
75 [EditorBrowsable(EditorBrowsableState.Never)]
76 protected override void Dispose(DisposeTypes type)
83 //Release your own unmanaged resources here.
84 //You should not access any managed member here except static instance.
85 //because the execution order of Finalizes is non-deterministic.
87 //disconnect event signal
88 if (finishedEventHandler != null && visualEventSignalCallback != null)
90 VisualEventSignal().Disconnect(visualEventSignalCallback);
91 finishedEventHandler = null;
92 NUILog.Debug($"disconnect event signal");
97 #endregion Constructor, Destructor, Dispose
102 /// Set or Get resource URL of Lottie file.
104 /// <since_tizen> 7 </since_tizen>
109 return GetValue(URLProperty) as string;
113 SetValue(URLProperty, value);
114 NotifyPropertyChanged();
118 private string InternalURL
122 string ret = (value == null ? "" : value);
123 currentStates.url = ret;
124 currentStates.changed = true;
126 NUILog.Debug($"<[{GetId()}]SET url={currentStates.url}");
128 PropertyMap map = new PropertyMap();
129 map.Add(Visual.Property.Type, new PropertyValue((int)DevelVisual.Type.AnimatedVectorImage))
130 .Add(ImageVisualProperty.URL, new PropertyValue(currentStates.url))
131 .Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount))
132 .Add(ImageVisualProperty.StopBehavior, new PropertyValue((int)currentStates.stopEndAction))
133 .Add(ImageVisualProperty.LoopingMode, new PropertyValue((int)currentStates.loopMode));
136 currentStates.contentInfo = null;
138 if (currentStates.scale != 1.0f)
140 Scale = new Vector3(currentStates.scale, currentStates.scale, 0.0f);
142 NUILog.Debug($"<[{GetId()}]>");
146 string ret = currentStates.url;
147 NUILog.Debug($"<[{GetId()}] GET");
149 PropertyMap map = Image;
152 PropertyValue val = map.Find(ImageVisualProperty.URL);
155 if (val.Get(out ret))
157 NUILog.Debug($"gotten url={ret} >");
162 Tizen.Log.Error(tag, $" [ERROR][{GetId()}](LottieAnimationView) Fail to get URL from dali >");
168 /// Gets the playing state
170 /// <since_tizen> 7 </since_tizen>
171 public PlayStateType PlayState
175 NUILog.Debug($"< Get!");
176 PropertyMap map = base.Image;
180 PropertyValue val = map.Find(ImageVisualProperty.PlayState);
183 if (val.Get(out ret))
185 currentStates.playState = (PlayStateType)ret;
186 NUILog.Debug($"gotten play state={ret} >");
192 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}]Fail to get PlayState from dali currentStates.playState={currentStates.playState}>");
194 return currentStates.playState;
199 /// Get the number of total frames
201 /// <since_tizen> 7 </since_tizen>
202 public int TotalFrame
207 PropertyMap map = Image;
210 PropertyValue val = map.Find(ImageVisualProperty.TotalFrameNumber);
213 if (val.Get(out ret))
215 //NUILog.Debug( $"TotalFrameNumber get! ret={ret}");
216 currentStates.totalFrame = ret;
221 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get TotalFrameNumber from dali>");
227 /// Set or get the current frame. When setting a specific frame, it is displayed as a still image.
230 /// Gets the value set by a user. If the setting value is out-ranged, it is reset as a minimum frame or a maximum frame.
233 /// We assume that the animation in myLottie.json file has 100 frames originally. If so, its frame index will be 0 - 99.
235 /// LottieAnimationView myLottie = new LottieAnimationView();
236 /// myLottie.URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "myLottie.json"; //myLottie.json's total frame is 100 (frame: 0~99)
237 /// NUIApplication.GetDefaultWindow().GetDefaultLayer().Add(myLottie);
238 /// myLottie.CurrentFrame = 200; //display 99 frame
239 /// myLottie.SetMinMaxFrame(10, 20);
240 /// myLottie.CurrentFrame = 15; //display 15 frame
241 /// myLottie.CurrentFrame = 50; //display 20 frame, because the MinMax is set (10,20) above
244 /// <since_tizen> 7 </since_tizen>
245 public int CurrentFrame
249 return (int)GetValue(CurrentFrameProperty);
253 SetValue(CurrentFrameProperty, value);
254 NotifyPropertyChanged();
258 private int InternalCurrentFrame
262 currentStates.frame = value;
263 NUILog.Debug($"<[{GetId()}]SET frame={currentStates.frame}>");
264 DoAction(ImageView.Property.IMAGE, ActionJumpTo, new PropertyValue(currentStates.frame));
269 PropertyMap map = Image;
272 PropertyValue val = map.Find(ImageVisualProperty.CurrentFrameNumber);
275 if (val.Get(out ret))
277 //NUILog.Debug( $"CurrentFrameNumber get! val={ret}");
282 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get CurrentFrameNumber from dali!! ret={ret}>");
288 /// Sets or gets the looping mode of Lottie animation.
290 /// <since_tizen> 7 </since_tizen>
291 public LoopingModeType LoopingMode
295 return (LoopingModeType)GetValue(LoopingModeProperty);
299 SetValue(LoopingModeProperty, value);
300 NotifyPropertyChanged();
304 private LoopingModeType InternalLoopingMode
308 currentStates.loopMode = (LoopingModeType)value;
309 currentStates.changed = true;
311 NUILog.Debug($"<[{GetId()}] SET loopMode={currentStates.loopMode}>");
312 PropertyMap map = new PropertyMap();
313 map.Add(ImageVisualProperty.LoopingMode, new PropertyValue((int)currentStates.loopMode));
314 DoAction(ImageView.Property.IMAGE, Interop.Visual.GetActionUpdateProperty(), new PropertyValue(map));
318 //NUILog.Debug( $"LoopMode get!");
319 PropertyMap map = base.Image;
323 PropertyValue val = map.Find(ImageVisualProperty.LoopingMode);
326 if (val.Get(out ret))
328 //NUILog.Debug( $"gotten LoopMode={ret}");
329 if (ret != (int)currentStates.loopMode && ret > 0)
331 NUILog.Debug($" [ERROR][{GetId()}](LottieAnimationView) different LoopMode! gotten={ret}, loopMode={currentStates.loopMode}");
333 currentStates.loopMode = (LoopingModeType)ret;
334 return (LoopingModeType)ret;
338 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get loopMode from dali>");
339 return currentStates.loopMode;
344 /// Sets or gets the loop count.
347 /// The minus value means the infinite loop count.
351 /// LottieAnimationView myLottie = new LottieAnimationView();
352 /// myLottie.URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "myLottie.json"; //myLottie.json's total frame is 100 (frame: 0~99)
353 /// NUIApplication.GetDefaultWindow().GetDefaultLayer().Add(myLottie);
354 /// myLottie.LoopCount = -1; //infinite loop
356 /// myLottie.Stop(); //it plays continuously unless Stop() is called
357 /// myLottie.LoopCount = 2;
358 /// myLottie.Play(); //it plays only 2 times and stops automatically
361 /// <since_tizen> 7 </since_tizen>
366 return (int)GetValue(LoopCountProperty);
370 SetValue(LoopCountProperty, value);
371 NotifyPropertyChanged();
375 private int InternalLoopCount
379 currentStates.changed = true;
380 currentStates.loopCount = value;
381 NUILog.Debug($"<[{GetId()}]SET currentStates.loopCount={currentStates.loopCount}>");
382 PropertyMap map = new PropertyMap();
383 map.Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount));
384 DoAction(ImageView.Property.IMAGE, Interop.Visual.GetActionUpdateProperty(), new PropertyValue(map));
388 //NUILog.Debug( $"LoopCount get!");
389 PropertyMap map = base.Image;
393 PropertyValue val = map.Find(ImageVisualProperty.LoopCount);
396 if (val.Get(out ret))
398 //NUILog.Debug( $"gotten loop count={ret}");
399 if (ret != currentStates.loopCount && ret > 0)
401 NUILog.Debug($"<[ERROR][{GetId()}](LottieAnimationView) different loop count! gotten={ret}, loopCount={currentStates.loopCount}>");
403 currentStates.loopCount = ret;
404 return currentStates.loopCount;
408 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get LoopCount from dali currentStates.loopCount={currentStates.loopCount}>");
409 return currentStates.loopCount;
414 /// Sets or gets the stop behavior.
416 /// <since_tizen> 7 </since_tizen>
417 public StopBehaviorType StopBehavior
421 return (StopBehaviorType)GetValue(StopBehaviorProperty);
425 SetValue(StopBehaviorProperty, value);
426 NotifyPropertyChanged();
430 private StopBehaviorType InternalStopBehavior
434 currentStates.stopEndAction = (StopBehaviorType)value;
435 currentStates.changed = true;
437 NUILog.Debug($"<[{GetId()}]SET val={currentStates.stopEndAction}>");
438 PropertyMap map = new PropertyMap();
439 map.Add(ImageVisualProperty.StopBehavior, new PropertyValue((int)currentStates.stopEndAction));
440 DoAction(ImageView.Property.IMAGE, Interop.Visual.GetActionUpdateProperty(), new PropertyValue(map));
444 //NUILog.Debug( $"StopBehavior get!");
445 PropertyMap map = base.Image;
449 PropertyValue val = map.Find(ImageVisualProperty.StopBehavior);
452 if (val.Get(out ret))
454 //NUILog.Debug( $"gotten StopBehavior={ret}");
455 if (ret != (int)currentStates.stopEndAction)
457 NUILog.Debug($"<[ERROR][{GetId()}](LottieAnimationView) different StopBehavior! gotten={ret}, StopBehavior={currentStates.stopEndAction}>");
459 currentStates.stopEndAction = (StopBehaviorType)ret;
460 return (StopBehaviorType)ret;
464 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get StopBehavior from dali>");
465 return currentStates.stopEndAction;
470 /// Whether to redraw the image when the visual is scaled down.
474 /// It is used in the AnimatedVectorImageVisual.The default is true.
476 [EditorBrowsable(EditorBrowsableState.Never)]
477 public bool RedrawInScalingDown
481 return (bool)GetValue(RedrawInScalingDownProperty);
485 SetValue(RedrawInScalingDownProperty, value);
486 NotifyPropertyChanged();
490 private bool InternalRedrawInScalingDown
494 currentStates.changed = true;
495 currentStates.redrawInScalingDown = value;
496 NUILog.Debug($"<[{GetId()}]SET currentStates.redrawInScalingDown={currentStates.redrawInScalingDown}>");
497 PropertyMap map = new PropertyMap();
498 map.Add(ImageVisualProperty.RedrawInScalingDown, new PropertyValue(currentStates.redrawInScalingDown));
499 DoAction(ImageView.Property.IMAGE, Interop.Visual.GetActionUpdateProperty(), new PropertyValue(map));
503 PropertyMap map = base.Image;
507 PropertyValue val = map.Find(ImageVisualProperty.RedrawInScalingDown);
510 if (val.Get(out ret))
512 if (ret != currentStates.redrawInScalingDown)
514 NUILog.Debug($"<[ERROR][{GetId()}](LottieAnimationView) different redrawInScalingDown! gotten={ret}, redrawInScalingDown={currentStates.redrawInScalingDown}>");
516 currentStates.redrawInScalingDown = ret;
517 return currentStates.redrawInScalingDown;
521 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get redrawInScalingDown from dali currentStates.redrawInScalingDown={currentStates.redrawInScalingDown}>");
522 return currentStates.redrawInScalingDown;
528 /// Actions property value to Jump to the specified frame.
529 /// This property can be redefined by child class if it use different value.
531 protected internal int ActionJumpTo { get; set; } = Interop.LottieAnimationView.AnimatedVectorImageVisualActionJumpToGet();
537 /// Set the minimum and the maximum frame.
539 /// <param name="minFrame">minimum frame</param>
540 /// <param name="maxFrame">maximum frame</param>
541 /// <since_tizen> 7 </since_tizen>
542 public void SetMinMaxFrame(int minFrame, int maxFrame)
544 NUILog.Debug($"< [{GetId()}] SetPlayRange({minFrame}, {maxFrame})");
546 currentStates.changed = true;
547 currentStates.framePlayRangeMin = minFrame;
548 currentStates.framePlayRangeMax = maxFrame;
550 PropertyArray array = new PropertyArray();
551 array.PushBack(new PropertyValue(currentStates.framePlayRangeMin));
552 array.PushBack(new PropertyValue(currentStates.framePlayRangeMax));
554 PropertyMap map = new PropertyMap();
555 map.Add(ImageVisualProperty.PlayRange, new PropertyValue(array));
556 DoAction(ImageView.Property.IMAGE, Interop.Visual.GetActionUpdateProperty(), new PropertyValue(map));
557 NUILog.Debug($" [{GetId()}] currentStates.min:({currentStates.framePlayRangeMin}, max:{currentStates.framePlayRangeMax})>");
563 /// <since_tizen> 7 </since_tizen>
564 public new void Play()
566 NUILog.Debug($"<[{GetId()}] Play()");
569 NUILog.Debug($"[{GetId()}]>");
575 /// <since_tizen> 7 </since_tizen>
576 public new void Pause()
578 NUILog.Debug($"<[{GetId()}] Pause()>");
581 NUILog.Debug($"[{GetId()}]>");
587 /// <since_tizen> 7 </since_tizen>
588 public new void Stop()
590 NUILog.Debug($"<[{GetId()}] Stop()");
593 NUILog.Debug($"[{GetId()}]>");
597 /// Get the list of layers' information such as the start frame and the end frame in the Lottie file.
599 /// <returns>List of Tuple (string of layer name, integer of start frame, integer of end frame)</returns>
600 /// <since_tizen> 7 </since_tizen>
601 public List<Tuple<string, int, int>> GetContentInfo()
604 if (currentStates.contentInfo != null)
606 return currentStates.contentInfo;
609 PropertyMap imageMap = base.Image;
610 PropertyMap contentMap = new PropertyMap();
611 if (imageMap != null)
613 PropertyValue val = imageMap.Find(ImageVisualProperty.ContentInfo);
616 if (val.Get(contentMap))
618 currentStates.contentInfo = new List<Tuple<string, int, int>>();
619 for (uint i = 0; i < contentMap.Count(); i++)
621 string key = contentMap.GetKeyAt(i).StringKey;
622 PropertyArray arr = new PropertyArray();
623 contentMap.GetValue(i).Get(arr);
626 int startFrame, endFrame;
627 arr.GetElementAt(0).Get(out startFrame);
628 arr.GetElementAt(1).Get(out endFrame);
630 NUILog.Debug($"[{i}] layer name={key}, startFrame={startFrame}, endFrame={endFrame}");
632 Tuple<string, int, int> item = new Tuple<string, int, int>(key, startFrame, endFrame);
634 currentStates.contentInfo?.Add(item);
641 return currentStates.contentInfo;
645 /// A marker has its start frame and end frame.
646 /// Animation will play between the start frame and the end frame of the marker if one marker is specified.
647 /// Or animation will play between the start frame of the first marker and the end frame of the second marker if two markers are specified. *
649 /// <param name="marker1">First marker</param>
650 /// <param name="marker2">Second marker</param>
651 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
652 [EditorBrowsable(EditorBrowsableState.Never)]
653 public void SetMinMaxFrameByMarker(string marker1, string marker2 = null)
655 NUILog.Debug($"< [{GetId()}] SetMinMaxFrameByMarker({marker1}, {marker2})");
657 currentStates.changed = true;
658 currentStates.mark1 = marker1;
659 currentStates.mark2 = marker2;
661 PropertyArray array = new PropertyArray();
662 array.PushBack(new PropertyValue(currentStates.mark1));
665 array.PushBack(new PropertyValue(currentStates.mark2));
668 PropertyMap map = new PropertyMap();
669 map.Add(ImageVisualProperty.PlayRange, new PropertyValue(array));
670 DoAction(ImageView.Property.IMAGE, Interop.Visual.GetActionUpdateProperty(), new PropertyValue(map));
671 NUILog.Debug($" [{GetId()}] currentStates.mark1:{currentStates.mark1}, mark2:{currentStates.mark2} >");
677 /// <returns>Tuple of Min and Max frames</returns>
678 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
679 [EditorBrowsable(EditorBrowsableState.Never)]
680 public Tuple<int, int> GetMinMaxFrame()
682 NUILog.Debug($"< [{GetId()}] GetMinMaxFrame()! total frame={currentStates.totalFrame}");
684 PropertyMap map = Image;
687 PropertyValue val = map.Find(ImageVisualProperty.PlayRange);
690 PropertyArray array = new PropertyArray();
693 uint cnt = array.Count();
694 int item1 = -1, item2 = -1;
695 for (uint i = 0; i < cnt; i++)
697 PropertyValue v = array.GetElementAt(i);
699 if (v.Get(out intRet))
701 NUILog.Debug($"Got play range of string [{i}]: {intRet}");
713 Tizen.Log.Error("NUI", $"[ERR] fail to get play range from dali! case#1");
716 NUILog.Debug($" [{GetId()}] GetMinMaxFrame(min:{item1}, max:{item2})! >");
717 return new Tuple<int, int>(item1, item2);
721 Tizen.Log.Error("NUI", $"[ERR] fail to get play range from dali! case#2");
722 return new Tuple<int, int>(-1, -1);
727 #region Event, Enum, Struct, ETC
729 /// Animation finished event.
731 /// <since_tizen> 7 </since_tizen>
732 public event EventHandler Finished
736 if (finishedEventHandler == null)
738 NUILog.Debug($"<[{GetId()}] Finished eventhandler added>");
739 visualEventSignalCallback = onVisualEventSignal;
740 VisualEventSignal().Connect(visualEventSignalCallback);
742 finishedEventHandler += value;
746 NUILog.Debug($"<[{GetId()}] Finished eventhandler removed>");
747 finishedEventHandler -= value;
748 if (finishedEventHandler == null && visualEventSignalCallback != null)
750 VisualEventSignal().Disconnect(visualEventSignalCallback);
756 /// Enumeration for what state the vector animation is in
758 /// <since_tizen> 7 </since_tizen>
759 public enum PlayStateType
764 /// <since_tizen> 7 </since_tizen>
767 /// Vector Animation has stopped
769 /// <since_tizen> 7 </since_tizen>
772 /// The vector animation is playing
774 /// <since_tizen> 7 </since_tizen>
777 /// The vector animation is paused
779 /// <since_tizen> 7 </since_tizen>
784 /// Enumeration for what to do when the animation is stopped.
786 /// <since_tizen> 7 </since_tizen>
787 public enum StopBehaviorType
790 /// When the animation is stopped, the current frame is shown.
792 /// <since_tizen> 7 </since_tizen>
795 /// When the animation is stopped, the min frame (first frame) is shown.
797 /// <since_tizen> 7 </since_tizen>
800 /// When the animation is stopped, the max frame (last frame) is shown.
802 /// <since_tizen> 7 </since_tizen>
807 /// Enumeration for what looping mode is in.
809 /// <since_tizen> 7 </since_tizen>
810 public enum LoopingModeType
813 /// When the animation arrives at the end in looping mode, the animation restarts from the beginning.
815 /// <since_tizen> 7 </since_tizen>
818 /// When the animation arrives at the end in looping mode, the animation reverses direction and runs backwards again.
820 /// <since_tizen> 7 </since_tizen>
823 #endregion Event, Enum, Struct, ETC
827 internal class VisualEventSignalArgs : EventArgs
829 public int VisualIndex
841 internal event EventHandler<VisualEventSignalArgs> VisualEvent
845 if (visualEventSignalHandler == null)
847 visualEventSignalCallback = onVisualEventSignal;
848 VisualEventSignal().Connect(visualEventSignalCallback);
850 visualEventSignalHandler += value;
854 visualEventSignalHandler -= value;
855 if (visualEventSignalHandler == null && VisualEventSignal().Empty() == false)
857 VisualEventSignal().Disconnect(visualEventSignalCallback);
862 internal void EmitVisualEventSignal(int visualIndex, int signalId)
864 VisualEventSignal().Emit(this, visualIndex, signalId);
867 internal VisualEventSignal VisualEventSignal()
869 VisualEventSignal ret = new VisualEventSignal(Interop.VisualEventSignal.NewWithView(View.getCPtr(this)), false);
870 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
877 private struct states
881 internal int loopCount;
882 internal LoopingModeType loopMode;
883 internal StopBehaviorType stopEndAction;
884 internal int framePlayRangeMin;
885 internal int framePlayRangeMax;
886 internal bool changed;
887 internal int totalFrame;
888 internal float scale;
889 internal PlayStateType playState;
890 internal List<Tuple<string, int, int>> contentInfo;
891 internal string mark1, mark2;
892 internal bool redrawInScalingDown;
894 private states currentStates;
896 private struct DevelVisual
900 AnimatedGradient = Visual.Type.AnimatedImage + 1,
901 AnimatedVectorImage = Visual.Type.AnimatedImage + 2,
905 private const string tag = "NUITEST";
906 private event EventHandler finishedEventHandler;
908 private void OnFinished()
910 NUILog.Debug($"<[{GetId()}] OnFinished()>");
911 finishedEventHandler?.Invoke(this, null);
914 private void onVisualEventSignal(IntPtr targetView, int visualIndex, int signalId)
918 if (targetView != IntPtr.Zero)
920 View v = Registry.GetManagedBaseHandleFromNativePtr(targetView) as View;
923 NUILog.Debug($"targetView is not null! name={v.Name}");
927 NUILog.Debug($"target is something created from dali");
930 VisualEventSignalArgs e = new VisualEventSignalArgs();
931 e.VisualIndex = visualIndex;
932 e.SignalId = signalId;
933 visualEventSignalHandler?.Invoke(this, e);
935 NUILog.Debug($"<[{GetId()}] onVisualEventSignal()! visualIndex={visualIndex}, signalId={signalId}>");
938 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
939 private delegate void VisualEventSignalCallbackType(IntPtr targetView, int visualIndex, int signalId);
941 private VisualEventSignalCallbackType visualEventSignalCallback;
942 private EventHandler<VisualEventSignalArgs> visualEventSignalHandler;
944 private void debugPrint()
946 NUILog.Debug($"===================================");
947 NUILog.Debug($"<[{GetId()}] get currentStates : url={currentStates.url}, loopCount={currentStates.loopCount}, \nframePlayRangeMin/Max({currentStates.framePlayRangeMin},{currentStates.framePlayRangeMax}) ");
948 NUILog.Debug($" get from Property : StopBehavior={StopBehavior}, LoopMode={LoopingMode}, LoopCount={LoopCount}, PlayState={PlayState}");
949 NUILog.Debug($" RedrawInScalingDown={RedrawInScalingDown} >");
950 NUILog.Debug($"===================================");
956 /// A class containing frame informations for a LottieAnimationView.
958 [EditorBrowsable(EditorBrowsableState.Never)]
959 public class LottieFrameInfo : ICloneable
962 /// Creates a new instance with a playing range.
964 [EditorBrowsable(EditorBrowsableState.Never)]
965 public LottieFrameInfo(int startFrame, int endFrame)
967 StartFrame = startFrame;
972 /// Creates a new instance with a still image frame.
974 [EditorBrowsable(EditorBrowsableState.Never)]
975 public LottieFrameInfo(int stillImageFrame) : this(stillImageFrame, stillImageFrame)
980 /// Create a new instance from a pair notation.
982 [EditorBrowsable(EditorBrowsableState.Never)]
983 public static implicit operator LottieFrameInfo((int, int) pair)
985 return new LottieFrameInfo(pair.Item1, pair.Item2);
989 /// Create a new instance from an int value.
991 [EditorBrowsable(EditorBrowsableState.Never)]
992 public static implicit operator LottieFrameInfo(int stillImageFrame)
994 return new LottieFrameInfo(stillImageFrame);
998 /// Create a new instance from string.
999 /// Possible input : "0, 10", "10"
1001 [EditorBrowsable(EditorBrowsableState.Never)]
1002 public static implicit operator LottieFrameInfo(string pair)
1009 string[] parts = pair.Split(',');
1010 if (parts.Length == 1)
1012 return new LottieFrameInfo(Int32.Parse(parts[0].Trim(), CultureInfo.InvariantCulture));
1014 else if (parts.Length == 2)
1016 return new LottieFrameInfo(Int32.Parse(parts[0].Trim(), CultureInfo.InvariantCulture), Int32.Parse(parts[1].Trim(), CultureInfo.InvariantCulture));
1019 Tizen.Log.Error("NUI", $"Can not convert string {pair} to LottieFrameInfo");
1024 /// The start frame of the lottie animation.
1026 [EditorBrowsable(EditorBrowsableState.Never)]
1027 public int StartFrame { get; }
1030 /// The end frame of the lottie animation.
1032 [EditorBrowsable(EditorBrowsableState.Never)]
1033 public int EndFrame { get; }
1036 /// Create LottieFrameInfo struct with animation range information
1038 [EditorBrowsable(EditorBrowsableState.Never)]
1039 public static LottieFrameInfo CreateAnimationRange(int startFrame, int endFrame)
1041 return new LottieFrameInfo(startFrame, endFrame);
1045 /// Create LottieFrameInfo struct with still image information
1047 [EditorBrowsable(EditorBrowsableState.Never)]
1048 public static LottieFrameInfo CreateStillImage(int stillImageFrame)
1050 return new LottieFrameInfo(stillImageFrame, stillImageFrame);
1055 /// Whether this LottieFrameInfo represents one frame or more.
1057 [EditorBrowsable(EditorBrowsableState.Never)]
1058 public bool IsStillImage()
1060 return StartFrame == EndFrame;
1065 /// Play specified LottieAnimationView with this frame information.
1067 /// <param name="lottieView">The target LottieAnimationView to play.</param>
1068 /// <param name="noPlay">Whether go direct to the EndFrame. It is false by default.</param>
1069 [EditorBrowsable(EditorBrowsableState.Never)]
1070 public void Show(LottieAnimationView lottieView, bool noPlay = false)
1072 if (!BeReadyToShow(lottieView))
1077 lottieView.SetMinMaxFrame(StartFrame, Math.Min(EndFrame, lottieView.TotalFrame - 1));
1079 if (IsStillImage() || noPlay)
1081 lottieView.CurrentFrame = EndFrame;
1085 lottieView.CurrentFrame = StartFrame;
1091 [EditorBrowsable(EditorBrowsableState.Never)]
1092 public object Clone() => new LottieFrameInfo(StartFrame, EndFrame);
1094 private bool BeReadyToShow(LottieAnimationView lottieView)
1096 // Validate input lottieView
1097 if (null == lottieView || lottieView.PlayState == LottieAnimationView.PlayStateType.Invalid)
1102 // Stop if it was playing
1103 if (lottieView.PlayState == LottieAnimationView.PlayStateType.Playing)