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 using tlog = Tizen.Log;
31 /// LottieAnimationView renders an animated vector image (Lottie file).
33 /// <since_tizen> 7 </since_tizen>
34 public partial class LottieAnimationView : ImageView
36 #region Constructor, Destructor, Dispose
38 /// LottieAnimationView constructor
40 /// <param name="scale">The factor of scaling image, default : 1.0f</param>
41 /// <param name="shown">false : not displayed (hidden), true : displayed (shown), default : true</param>
43 /// If the shown parameter is false, the animation is not visible even if the LottieAnimationView instance is created.
47 /// LottieAnimationView myLottie = new LottieAnimationView();
48 /// LottieAnimationView myLottie2 = new LottieAnimationView(2.0f);
49 /// LottieAnimationView myLottie3 = new LottieAnimationView(1.0f, false);
52 /// <since_tizen> 7 </since_tizen>
53 public LottieAnimationView(float scale = 1.0f, bool shown = true) : base()
55 tlog.Fatal(tag, $"< 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 tlog.Fatal(tag, $"<[{GetId()}] type={type}");
85 //Release your own unmanaged resources here.
86 //You should not access any managed member here except static instance.
87 //because the execution order of Finalizes is non-deterministic.
89 //disconnect event signal
90 if (finishedEventHandler != null && visualEventSignalCallback != null)
92 VisualEventSignal().Disconnect(visualEventSignalCallback);
93 finishedEventHandler = null;
94 tlog.Fatal(tag, $"disconnect event signal");
98 tlog.Fatal(tag, $"[{GetId()}]>");
100 #endregion Constructor, Destructor, Dispose
105 /// Set or Get resource URL of Lottie file.
107 /// <since_tizen> 7 </since_tizen>
112 return GetValue(URLProperty) as string;
116 SetValue(URLProperty, value);
117 NotifyPropertyChanged();
121 private string InternalURL
125 string ret = (value == null ? "" : value);
126 currentStates.url = ret;
127 currentStates.changed = true;
129 tlog.Fatal(tag, $"<[{GetId()}]SET url={currentStates.url}");
131 PropertyMap map = new PropertyMap();
132 map.Add(Visual.Property.Type, new PropertyValue((int)DevelVisual.Type.AnimatedVectorImage))
133 .Add(ImageVisualProperty.URL, new PropertyValue(currentStates.url))
134 .Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount))
135 .Add(ImageVisualProperty.StopBehavior, new PropertyValue((int)currentStates.stopEndAction))
136 .Add(ImageVisualProperty.LoopingMode, new PropertyValue((int)currentStates.loopMode));
139 currentStates.contentInfo = null;
141 if (currentStates.scale != 1.0f)
143 Scale = new Vector3(currentStates.scale, currentStates.scale, 0.0f);
145 tlog.Fatal(tag, $"<[{GetId()}]>");
149 string ret = currentStates.url;
150 tlog.Fatal(tag, $"<[{GetId()}] GET");
152 PropertyMap map = Image;
155 PropertyValue val = map.Find(ImageVisualProperty.URL);
158 if (val.Get(out ret))
160 tlog.Fatal(tag, $"gotten url={ret} >");
165 Tizen.Log.Error(tag, $" [ERROR][{GetId()}](LottieAnimationView) Fail to get URL from dali >");
171 /// Gets the playing state
173 /// <since_tizen> 7 </since_tizen>
174 public PlayStateType PlayState
178 tlog.Fatal(tag, $"< Get!");
179 PropertyMap map = base.Image;
183 PropertyValue val = map.Find(ImageVisualProperty.PlayState);
186 if (val.Get(out ret))
188 currentStates.playState = (PlayStateType)ret;
189 tlog.Fatal(tag, $"gotten play state={ret} >");
195 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}]Fail to get PlayState from dali currentStates.playState={currentStates.playState}>");
197 return currentStates.playState;
202 /// Get the number of total frames
204 /// <since_tizen> 7 </since_tizen>
205 public int TotalFrame
210 PropertyMap map = Image;
213 PropertyValue val = map.Find(ImageVisualProperty.TotalFrameNumber);
216 if (val.Get(out ret))
218 //tlog.Fatal(tag, $"TotalFrameNumber get! ret={ret}");
219 currentStates.totalFrame = ret;
224 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get TotalFrameNumber from dali>");
230 /// Set or get the current frame. When setting a specific frame, it is displayed as a still image.
233 /// 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.
236 /// We assume that the animation in myLottie.json file has 100 frames originally. If so, its frame index will be 0 - 99.
238 /// LottieAnimationView myLottie = new LottieAnimationView();
239 /// myLottie.URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "myLottie.json"; //myLottie.json's total frame is 100 (frame: 0~99)
240 /// NUIApplication.GetDefaultWindow().GetDefaultLayer().Add(myLottie);
241 /// myLottie.CurrentFrame = 200; //display 99 frame
242 /// myLottie.SetMinMaxFrame(10, 20);
243 /// myLottie.CurrentFrame = 15; //display 15 frame
244 /// myLottie.CurrentFrame = 50; //display 20 frame, because the MinMax is set (10,20) above
247 /// <since_tizen> 7 </since_tizen>
248 public int CurrentFrame
252 return (int)GetValue(CurrentFrameProperty);
256 SetValue(CurrentFrameProperty, value);
257 NotifyPropertyChanged();
261 private int InternalCurrentFrame
265 currentStates.frame = value;
266 tlog.Fatal(tag, $"<[{GetId()}]SET frame={currentStates.frame}>");
267 DoAction(ImageView.Property.IMAGE, (int)actionType.jumpTo, new PropertyValue(currentStates.frame));
272 PropertyMap map = Image;
275 PropertyValue val = map.Find(ImageVisualProperty.CurrentFrameNumber);
278 if (val.Get(out ret))
280 //tlog.Fatal(tag, $"CurrentFrameNumber get! val={ret}");
285 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get CurrentFrameNumber from dali!! ret={ret}>");
291 /// Sets or gets the looping mode of Lottie animation.
293 /// <since_tizen> 7 </since_tizen>
294 public LoopingModeType LoopingMode
298 return (LoopingModeType)GetValue(LoopingModeProperty);
302 SetValue(LoopingModeProperty, value);
303 NotifyPropertyChanged();
307 private LoopingModeType InternalLoopingMode
311 currentStates.loopMode = (LoopingModeType)value;
312 currentStates.changed = true;
314 tlog.Fatal(tag, $"<[{GetId()}] SET loopMode={currentStates.loopMode}>");
315 PropertyMap map = new PropertyMap();
316 map.Add(ImageVisualProperty.LoopingMode, new PropertyValue((int)currentStates.loopMode));
317 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
321 //tlog.Fatal(tag, $"LoopMode get!");
322 PropertyMap map = base.Image;
326 PropertyValue val = map.Find(ImageVisualProperty.LoopingMode);
329 if (val.Get(out ret))
331 //tlog.Fatal(tag, $"gotten LoopMode={ret}");
332 if (ret != (int)currentStates.loopMode && ret > 0)
334 tlog.Fatal(tag, $" [ERROR][{GetId()}](LottieAnimationView) different LoopMode! gotten={ret}, loopMode={currentStates.loopMode}");
336 currentStates.loopMode = (LoopingModeType)ret;
337 return (LoopingModeType)ret;
341 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get loopMode from dali>");
342 return currentStates.loopMode;
347 /// Sets or gets the loop count.
350 /// The minus value means the infinite loop count.
354 /// LottieAnimationView myLottie = new LottieAnimationView();
355 /// myLottie.URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "myLottie.json"; //myLottie.json's total frame is 100 (frame: 0~99)
356 /// NUIApplication.GetDefaultWindow().GetDefaultLayer().Add(myLottie);
357 /// myLottie.LoopCount = -1; //infinite loop
359 /// myLottie.Stop(); //it plays continuously unless Stop() is called
360 /// myLottie.LoopCount = 2;
361 /// myLottie.Play(); //it plays only 2 times and stops automatically
364 /// <since_tizen> 7 </since_tizen>
369 return (int)GetValue(LoopCountProperty);
373 SetValue(LoopCountProperty, value);
374 NotifyPropertyChanged();
378 private int InternalLoopCount
382 currentStates.changed = true;
383 currentStates.loopCount = value;
384 tlog.Fatal(tag, $"<[{GetId()}]SET currentStates.loopCount={currentStates.loopCount}>");
385 PropertyMap map = new PropertyMap();
386 map.Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount));
387 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
391 //tlog.Fatal(tag, $"LoopCount get!");
392 PropertyMap map = base.Image;
396 PropertyValue val = map.Find(ImageVisualProperty.LoopCount);
399 if (val.Get(out ret))
401 //tlog.Fatal(tag, $"gotten loop count={ret}");
402 if (ret != currentStates.loopCount && ret > 0)
404 tlog.Fatal(tag, $"<[ERROR][{GetId()}](LottieAnimationView) different loop count! gotten={ret}, loopCount={currentStates.loopCount}>");
406 currentStates.loopCount = ret;
407 return currentStates.loopCount;
411 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get LoopCount from dali currentStates.loopCount={currentStates.loopCount}>");
412 return currentStates.loopCount;
417 /// Sets or gets the stop behavior.
419 /// <since_tizen> 7 </since_tizen>
420 public StopBehaviorType StopBehavior
424 return (StopBehaviorType)GetValue(StopBehaviorProperty);
428 SetValue(StopBehaviorProperty, value);
429 NotifyPropertyChanged();
433 private StopBehaviorType InternalStopBehavior
437 currentStates.stopEndAction = (StopBehaviorType)value;
438 currentStates.changed = true;
440 tlog.Fatal(tag, $"<[{GetId()}]SET val={currentStates.stopEndAction}>");
441 PropertyMap map = new PropertyMap();
442 map.Add(ImageVisualProperty.StopBehavior, new PropertyValue((int)currentStates.stopEndAction));
443 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
447 //tlog.Fatal(tag, $"StopBehavior get!");
448 PropertyMap map = base.Image;
452 PropertyValue val = map.Find(ImageVisualProperty.StopBehavior);
455 if (val.Get(out ret))
457 //tlog.Fatal(tag, $"gotten StopBehavior={ret}");
458 if (ret != (int)currentStates.stopEndAction)
460 tlog.Fatal(tag, $"<[ERROR][{GetId()}](LottieAnimationView) different StopBehavior! gotten={ret}, StopBehavior={currentStates.stopEndAction}>");
462 currentStates.stopEndAction = (StopBehaviorType)ret;
463 return (StopBehaviorType)ret;
467 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get StopBehavior from dali>");
468 return currentStates.stopEndAction;
473 /// Whether to redraw the image when the visual is scaled down.
477 /// It is used in the AnimatedVectorImageVisual.The default is true.
479 [EditorBrowsable(EditorBrowsableState.Never)]
480 public bool RedrawInScalingDown
484 return (bool)GetValue(RedrawInScalingDownProperty);
488 SetValue(RedrawInScalingDownProperty, value);
489 NotifyPropertyChanged();
493 private bool InternalRedrawInScalingDown
497 currentStates.changed = true;
498 currentStates.redrawInScalingDown = value;
499 tlog.Fatal(tag, $"<[{GetId()}]SET currentStates.redrawInScalingDown={currentStates.redrawInScalingDown}>");
500 PropertyMap map = new PropertyMap();
501 map.Add(ImageVisualProperty.RedrawInScalingDown, new PropertyValue(currentStates.redrawInScalingDown));
502 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
506 PropertyMap map = base.Image;
510 PropertyValue val = map.Find(ImageVisualProperty.RedrawInScalingDown);
513 if (val.Get(out ret))
515 if (ret != currentStates.redrawInScalingDown)
517 tlog.Fatal(tag, $"<[ERROR][{GetId()}](LottieAnimationView) different redrawInScalingDown! gotten={ret}, redrawInScalingDown={currentStates.redrawInScalingDown}>");
519 currentStates.redrawInScalingDown = ret;
520 return currentStates.redrawInScalingDown;
524 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get redrawInScalingDown from dali currentStates.redrawInScalingDown={currentStates.redrawInScalingDown}>");
525 return currentStates.redrawInScalingDown;
533 /// Set the minimum and the maximum frame.
535 /// <param name="minFrame">minimum frame</param>
536 /// <param name="maxFrame">maximum frame</param>
537 /// <since_tizen> 7 </since_tizen>
538 public void SetMinMaxFrame(int minFrame, int maxFrame)
540 tlog.Fatal(tag, $"< [{GetId()}] SetPlayRange({minFrame}, {maxFrame})");
542 currentStates.changed = true;
543 currentStates.framePlayRangeMin = minFrame;
544 currentStates.framePlayRangeMax = maxFrame;
546 PropertyArray array = new PropertyArray();
547 array.PushBack(new PropertyValue(currentStates.framePlayRangeMin));
548 array.PushBack(new PropertyValue(currentStates.framePlayRangeMax));
550 PropertyMap map = new PropertyMap();
551 map.Add(ImageVisualProperty.PlayRange, new PropertyValue(array));
552 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
553 tlog.Fatal(tag, $" [{GetId()}] currentStates.min:({currentStates.framePlayRangeMin}, max:{currentStates.framePlayRangeMax})>");
559 /// <since_tizen> 7 </since_tizen>
560 public new void Play()
562 tlog.Fatal(tag, $"<[{GetId()}] Play()");
565 tlog.Fatal(tag, $"[{GetId()}]>");
571 /// <since_tizen> 7 </since_tizen>
572 public new void Pause()
574 tlog.Fatal(tag, $"<[{GetId()}] Pause()>");
577 tlog.Fatal(tag, $"[{GetId()}]>");
583 /// <since_tizen> 7 </since_tizen>
584 public new void Stop()
586 tlog.Fatal(tag, $"<[{GetId()}] Stop()");
589 tlog.Fatal(tag, $"[{GetId()}]>");
593 /// Get the list of layers' information such as the start frame and the end frame in the Lottie file.
595 /// <returns>List of Tuple (string of layer name, integer of start frame, integer of end frame)</returns>
596 /// <since_tizen> 7 </since_tizen>
597 public List<Tuple<string, int, int>> GetContentInfo()
599 tlog.Fatal(tag, $"<");
600 if (currentStates.contentInfo != null)
602 return currentStates.contentInfo;
605 PropertyMap imageMap = base.Image;
606 PropertyMap contentMap = new PropertyMap();
607 if (imageMap != null)
609 PropertyValue val = imageMap.Find(ImageVisualProperty.ContentInfo);
612 if (val.Get(contentMap))
614 currentStates.contentInfo = new List<Tuple<string, int, int>>();
615 for (uint i = 0; i < contentMap.Count(); i++)
617 string key = contentMap.GetKeyAt(i).StringKey;
618 PropertyArray arr = new PropertyArray();
619 contentMap.GetValue(i).Get(arr);
622 int startFrame, endFrame;
623 arr.GetElementAt(0).Get(out startFrame);
624 arr.GetElementAt(1).Get(out endFrame);
626 tlog.Fatal(tag, $"[{i}] layer name={key}, startFrame={startFrame}, endFrame={endFrame}");
628 Tuple<string, int, int> item = new Tuple<string, int, int>(key, startFrame, endFrame);
630 currentStates.contentInfo?.Add(item);
636 tlog.Fatal(tag, $">");
637 return currentStates.contentInfo;
641 /// A marker has its start frame and end frame.
642 /// Animation will play between the start frame and the end frame of the marker if one marker is specified.
643 /// 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. *
645 /// <param name="marker1">First marker</param>
646 /// <param name="marker2">Second marker</param>
647 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
648 [EditorBrowsable(EditorBrowsableState.Never)]
649 public void SetMinMaxFrameByMarker(string marker1, string marker2 = null)
651 tlog.Fatal(tag, $"< [{GetId()}] SetMinMaxFrameByMarker({marker1}, {marker2})");
653 currentStates.changed = true;
654 currentStates.mark1 = marker1;
655 currentStates.mark2 = marker2;
657 PropertyArray array = new PropertyArray();
658 array.PushBack(new PropertyValue(currentStates.mark1));
661 array.PushBack(new PropertyValue(currentStates.mark2));
664 PropertyMap map = new PropertyMap();
665 map.Add(ImageVisualProperty.PlayRange, new PropertyValue(array));
666 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
667 tlog.Fatal(tag, $" [{GetId()}] currentStates.mark1:{currentStates.mark1}, mark2:{currentStates.mark2} >");
673 /// <returns>Tuple of Min and Max frames</returns>
674 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
675 [EditorBrowsable(EditorBrowsableState.Never)]
676 public Tuple<int, int> GetMinMaxFrame()
678 tlog.Fatal(tag, $"< [{GetId()}] GetMinMaxFrame()! total frame={currentStates.totalFrame}");
680 PropertyMap map = Image;
683 PropertyValue val = map.Find(ImageVisualProperty.PlayRange);
686 PropertyArray array = new PropertyArray();
689 uint cnt = array.Count();
690 int item1 = -1, item2 = -1;
691 for (uint i = 0; i < cnt; i++)
693 PropertyValue v = array.GetElementAt(i);
695 if (v.Get(out intRet))
697 tlog.Fatal(tag, $"Got play range of string [{i}]: {intRet}");
709 Tizen.Log.Error("NUI", $"[ERR] fail to get play range from dali! case#1");
712 tlog.Fatal(tag, $" [{GetId()}] GetMinMaxFrame(min:{item1}, max:{item2})! >");
713 return new Tuple<int, int>(item1, item2);
717 Tizen.Log.Error("NUI", $"[ERR] fail to get play range from dali! case#2");
718 return new Tuple<int, int>(-1, -1);
723 #region Event, Enum, Struct, ETC
725 /// Animation finished event.
727 /// <since_tizen> 7 </since_tizen>
728 public event EventHandler Finished
732 if (finishedEventHandler == null)
734 tlog.Fatal(tag, $"<[{GetId()}] Finished eventhandler added>");
735 visualEventSignalCallback = onVisualEventSignal;
736 VisualEventSignal().Connect(visualEventSignalCallback);
738 finishedEventHandler += value;
742 tlog.Fatal(tag, $"<[{GetId()}] Finished eventhandler removed>");
743 finishedEventHandler -= value;
744 if (finishedEventHandler == null && visualEventSignalCallback != null)
746 VisualEventSignal().Disconnect(visualEventSignalCallback);
752 /// Enumeration for what state the vector animation is in
754 /// <since_tizen> 7 </since_tizen>
755 public enum PlayStateType
760 /// <since_tizen> 7 </since_tizen>
763 /// Vector Animation has stopped
765 /// <since_tizen> 7 </since_tizen>
768 /// The vector animation is playing
770 /// <since_tizen> 7 </since_tizen>
773 /// The vector animation is paused
775 /// <since_tizen> 7 </since_tizen>
780 /// Enumeration for what to do when the animation is stopped.
782 /// <since_tizen> 7 </since_tizen>
783 public enum StopBehaviorType
786 /// When the animation is stopped, the current frame is shown.
788 /// <since_tizen> 7 </since_tizen>
791 /// When the animation is stopped, the min frame (first frame) is shown.
793 /// <since_tizen> 7 </since_tizen>
796 /// When the animation is stopped, the max frame (last frame) is shown.
798 /// <since_tizen> 7 </since_tizen>
803 /// Enumeration for what looping mode is in.
805 /// <since_tizen> 7 </since_tizen>
806 public enum LoopingModeType
809 /// When the animation arrives at the end in looping mode, the animation restarts from the beginning.
811 /// <since_tizen> 7 </since_tizen>
814 /// When the animation arrives at the end in looping mode, the animation reverses direction and runs backwards again.
816 /// <since_tizen> 7 </since_tizen>
819 #endregion Event, Enum, Struct, ETC
823 internal class VisualEventSignalArgs : EventArgs
825 public int VisualIndex
837 internal event EventHandler<VisualEventSignalArgs> VisualEvent
841 if (visualEventSignalHandler == null)
843 visualEventSignalCallback = onVisualEventSignal;
844 VisualEventSignal().Connect(visualEventSignalCallback);
846 visualEventSignalHandler += value;
850 visualEventSignalHandler -= value;
851 if (visualEventSignalHandler == null && VisualEventSignal().Empty() == false)
853 VisualEventSignal().Disconnect(visualEventSignalCallback);
858 internal void EmitVisualEventSignal(int visualIndex, int signalId)
860 VisualEventSignal().Emit(this, visualIndex, signalId);
863 internal VisualEventSignal VisualEventSignal()
865 VisualEventSignal ret = new VisualEventSignal(Interop.VisualEventSignal.NewWithView(View.getCPtr(this)), false);
866 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
873 private struct states
877 internal int loopCount;
878 internal LoopingModeType loopMode;
879 internal StopBehaviorType stopEndAction;
880 internal int framePlayRangeMin;
881 internal int framePlayRangeMax;
882 internal bool changed;
883 internal int totalFrame;
884 internal float scale;
885 internal PlayStateType playState;
886 internal List<Tuple<string, int, int>> contentInfo;
887 internal string mark1, mark2;
888 internal bool redrawInScalingDown;
890 private states currentStates;
892 private enum actionType
901 private struct DevelVisual
905 AnimatedGradient = Visual.Type.AnimatedImage + 1,
906 AnimatedVectorImage = Visual.Type.AnimatedImage + 2,
910 private const string tag = "NUITEST";
911 private event EventHandler finishedEventHandler;
913 private void OnFinished()
915 tlog.Fatal(tag, $"<[{GetId()}] OnFinished()>");
916 finishedEventHandler?.Invoke(this, null);
919 private void onVisualEventSignal(IntPtr targetView, int visualIndex, int signalId)
923 if (targetView != IntPtr.Zero)
925 View v = Registry.GetManagedBaseHandleFromNativePtr(targetView) as View;
928 tlog.Fatal(tag, $"targetView is not null! name={v.Name}");
932 tlog.Fatal(tag, $"target is something created from dali");
935 VisualEventSignalArgs e = new VisualEventSignalArgs();
936 e.VisualIndex = visualIndex;
937 e.SignalId = signalId;
938 visualEventSignalHandler?.Invoke(this, e);
940 tlog.Fatal(tag, $"<[{GetId()}] onVisualEventSignal()! visualIndex={visualIndex}, signalId={signalId}>");
943 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
944 private delegate void VisualEventSignalCallbackType(IntPtr targetView, int visualIndex, int signalId);
946 private VisualEventSignalCallbackType visualEventSignalCallback;
947 private EventHandler<VisualEventSignalArgs> visualEventSignalHandler;
949 private void debugPrint()
951 tlog.Fatal(tag, $"===================================");
952 tlog.Fatal(tag, $"<[{GetId()}] get currentStates : url={currentStates.url}, loopCount={currentStates.loopCount}, \nframePlayRangeMin/Max({currentStates.framePlayRangeMin},{currentStates.framePlayRangeMax}) ");
953 tlog.Fatal(tag, $" get from Property : StopBehavior={StopBehavior}, LoopMode={LoopingMode}, LoopCount={LoopCount}, PlayState={PlayState}");
954 tlog.Fatal(tag, $" RedrawInScalingDown={RedrawInScalingDown} >");
955 tlog.Fatal(tag, $"===================================");
961 /// A class containing frame informations for a LottieAnimationView.
963 [EditorBrowsable(EditorBrowsableState.Never)]
964 public class LottieFrameInfo : ICloneable
967 /// Creates a new instance with a playing range.
969 [EditorBrowsable(EditorBrowsableState.Never)]
970 public LottieFrameInfo(int startFrame, int endFrame)
972 StartFrame = startFrame;
977 /// Creates a new instance with a still image frame.
979 [EditorBrowsable(EditorBrowsableState.Never)]
980 public LottieFrameInfo(int stillImageFrame) : this(stillImageFrame, stillImageFrame)
985 /// Create a new instance from a pair notation.
987 [EditorBrowsable(EditorBrowsableState.Never)]
988 public static implicit operator LottieFrameInfo((int, int) pair)
990 return new LottieFrameInfo(pair.Item1, pair.Item2);
994 /// Create a new instance from an int value.
996 [EditorBrowsable(EditorBrowsableState.Never)]
997 public static implicit operator LottieFrameInfo(int stillImageFrame)
999 return new LottieFrameInfo(stillImageFrame);
1003 /// Create a new instance from string.
1004 /// Possible input : "0, 10", "10"
1006 [EditorBrowsable(EditorBrowsableState.Never)]
1007 public static implicit operator LottieFrameInfo(string pair)
1014 string[] parts = pair.Split(',');
1015 if (parts.Length == 1)
1017 return new LottieFrameInfo(Int32.Parse(parts[0].Trim(), CultureInfo.InvariantCulture));
1019 else if (parts.Length == 2)
1021 return new LottieFrameInfo(Int32.Parse(parts[0].Trim(), CultureInfo.InvariantCulture), Int32.Parse(parts[1].Trim(), CultureInfo.InvariantCulture));
1024 Tizen.Log.Error("NUI", $"Can not convert string {pair} to LottieFrameInfo");
1029 /// The start frame of the lottie animation.
1031 [EditorBrowsable(EditorBrowsableState.Never)]
1032 public int StartFrame { get; }
1035 /// The end frame of the lottie animation.
1037 [EditorBrowsable(EditorBrowsableState.Never)]
1038 public int EndFrame { get; }
1041 /// Create LottieFrameInfo struct with animation range information
1043 [EditorBrowsable(EditorBrowsableState.Never)]
1044 public static LottieFrameInfo CreateAnimationRange(int startFrame, int endFrame)
1046 return new LottieFrameInfo(startFrame, endFrame);
1050 /// Create LottieFrameInfo struct with still image information
1052 [EditorBrowsable(EditorBrowsableState.Never)]
1053 public static LottieFrameInfo CreateStillImage(int stillImageFrame)
1055 return new LottieFrameInfo(stillImageFrame, stillImageFrame);
1060 /// Whether this LottieFrameInfo represents one frame or more.
1062 [EditorBrowsable(EditorBrowsableState.Never)]
1063 public bool IsStillImage()
1065 return StartFrame == EndFrame;
1070 /// Play specified LottieAnimationView with this frame information.
1072 /// <param name="lottieView">The target LottieAnimationView to play.</param>
1073 /// <param name="noPlay">Whether go direct to the EndFrame. It is false by default.</param>
1074 [EditorBrowsable(EditorBrowsableState.Never)]
1075 public void Show(LottieAnimationView lottieView, bool noPlay = false)
1077 if (!BeReadyToShow(lottieView))
1082 lottieView.SetMinMaxFrame(StartFrame, Math.Min(EndFrame, lottieView.TotalFrame - 1));
1084 if (IsStillImage() || noPlay)
1086 lottieView.CurrentFrame = EndFrame;
1090 lottieView.CurrentFrame = StartFrame;
1096 [EditorBrowsable(EditorBrowsableState.Never)]
1097 public object Clone() => new LottieFrameInfo(StartFrame, EndFrame);
1099 private bool BeReadyToShow(LottieAnimationView lottieView)
1101 // Validate input lottieView
1102 if (null == lottieView || lottieView.PlayState == LottieAnimationView.PlayStateType.Invalid)
1107 // Stop if it was playing
1108 if (lottieView.PlayState == LottieAnimationView.PlayStateType.Playing)