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;
23 namespace Tizen.NUI.BaseComponents
26 using tlog = Tizen.Log;
30 /// LottieAnimationView renders an animated vector image (Lottie file).
32 /// <since_tizen> 7 </since_tizen>
33 public class LottieAnimationView : ImageView
35 #region Constructor, Distructor, Dispose
37 /// LottieAnimationView constructor
39 /// <param name="scale">The factor of scaling image, default : 1.0f</param>
40 /// <param name="shown">false : not displayed (hidden), true : displayed (shown), default : true</param>
42 /// If the shown parameter is false, the animation is not visible even if the LottieAnimationView instance is created.
46 /// LottieAnimationView myLottie = new LottieAnimationView();
47 /// LottieAnimationView myLottie2 = new LottieAnimationView(2.0f);
48 /// LottieAnimationView myLottie3 = new LottieAnimationView(1.0f, false);
51 /// <since_tizen> 7 </since_tizen>
52 public LottieAnimationView(float scale = 1.0f, bool shown = true) : base()
54 tlog.Fatal(tag, $"< constructor GetId={GetId()} >");
55 currentStates.url = "";
56 currentStates.frame = -1;
57 currentStates.loopCount = 1;
58 currentStates.loopMode = LoopingModeType.Restart;
59 currentStates.stopEndAction = StopBehaviorType.CurrentFrame;
60 currentStates.framePlayRangeMin = -1;
61 currentStates.framePlayRangeMax = -1;
62 currentStates.changed = false;
63 currentStates.totalFrame = -1;
64 currentStates.scale = scale;
65 currentStates.redrawInScalingDown = true;
70 /// Dispose(DisposeTypes type)
72 /// <param name="type"></param>
73 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
74 [EditorBrowsable(EditorBrowsableState.Never)]
75 protected override void Dispose(DisposeTypes type)
82 tlog.Fatal(tag, $"<[{GetId()}] type={type}");
84 //Release your own unmanaged resources here.
85 //You should not access any managed member here except static instance.
86 //because the execution order of Finalizes is non-deterministic.
88 //disconnect event signal
89 if (finishedEventHandler != null && visualEventSignalCallback != null)
91 VisualEventSignal().Disconnect(visualEventSignalCallback);
92 finishedEventHandler = null;
93 tlog.Fatal(tag, $"disconnect event signal");
97 tlog.Fatal(tag, $"[{GetId()}]>");
99 #endregion Constructor, Distructor, Dispose
104 /// Set or Get resource URL of Lottie file.
106 /// <since_tizen> 7 </since_tizen>
111 string ret = (value == null ? "" : value);
112 currentStates.url = ret;
113 currentStates.changed = true;
115 tlog.Fatal(tag, $"<[{GetId()}]SET url={currentStates.url}");
117 PropertyMap map = new PropertyMap();
118 map.Add(Visual.Property.Type, new PropertyValue((int)DevelVisual.Type.AnimatedVectorImage))
119 .Add(ImageVisualProperty.URL, new PropertyValue(currentStates.url))
120 .Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount))
121 .Add(ImageVisualProperty.StopBehavior, new PropertyValue((int)currentStates.stopEndAction))
122 .Add(ImageVisualProperty.LoopingMode, new PropertyValue((int)currentStates.loopMode));
125 currentStates.contentInfo = null;
127 if (currentStates.scale != 1.0f)
129 Scale = new Vector3(currentStates.scale, currentStates.scale, 0.0f);
131 tlog.Fatal(tag, $"<[{GetId()}]>");
135 string ret = currentStates.url;
136 tlog.Fatal(tag, $"<[{GetId()}] GET");
138 PropertyMap map = Image;
141 PropertyValue val = map.Find(ImageVisualProperty.URL);
144 if (val.Get(out ret))
146 tlog.Fatal(tag, $"gotten url={ret} >");
151 Tizen.Log.Error(tag, $" [ERROR][{GetId()}](LottieAnimationView) Fail to get URL from dali >");
157 /// Gets the playing state
159 /// <since_tizen> 7 </since_tizen>
160 public PlayStateType PlayState
164 tlog.Fatal(tag, $"< Get!");
165 PropertyMap map = base.Image;
169 PropertyValue val = map.Find(ImageVisualProperty.PlayState);
172 if (val.Get(out ret))
174 currentStates.playState = (PlayStateType)ret;
175 tlog.Fatal(tag, $"gotten play state={ret} >");
181 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}]Fail to get PlayState from dali currentStates.playState={currentStates.playState}>");
183 return currentStates.playState;
188 /// Get the number of total frames
190 /// <since_tizen> 7 </since_tizen>
191 public int TotalFrame
196 PropertyMap map = Image;
199 PropertyValue val = map.Find(ImageVisualProperty.TotalFrameNumber);
202 if (val.Get(out ret))
204 //tlog.Fatal(tag, $"TotalFrameNumber get! ret={ret}");
205 currentStates.totalFrame = ret;
210 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get TotalFrameNumber from dali>");
216 /// Set or get the current frame. When setting a specific frame, it is displayed as a still image.
219 /// 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.
222 /// We assume that the animation in myLottie.json file has 100 frames originally. If so, its frame index will be 0 - 99.
224 /// LottieAnimationView myLottie = new LottieAnimationView();
225 /// myLottie.URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "myLottie.json"; //myLottie.json's total frame is 100 (frame: 0~99)
226 /// NUIApplication.GetDefaultWindow().GetDefaultLayer().Add(myLottie);
227 /// myLottie.CurrentFrame = 200; //display 99 frame
228 /// myLottie.SetMinMaxFrame(10, 20);
229 /// myLottie.CurrentFrame = 15; //display 15 frame
230 /// myLottie.CurrentFrame = 50; //display 20 frame, because the MinMax is set (10,20) above
233 /// <since_tizen> 7 </since_tizen>
234 public int CurrentFrame
238 currentStates.frame = value;
239 tlog.Fatal(tag, $"<[{GetId()}]SET frame={currentStates.frame}>");
240 DoAction(ImageView.Property.IMAGE, (int)actionType.jumpTo, new PropertyValue(currentStates.frame));
245 PropertyMap map = Image;
248 PropertyValue val = map.Find(ImageVisualProperty.CurrentFrameNumber);
251 if (val.Get(out ret))
253 //tlog.Fatal(tag, $"CurrentFrameNumber get! val={ret}");
258 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get CurrentFrameNumber from dali!! ret={ret}>");
264 /// Sets or gets the looping mode of Lottie animation.
266 /// <since_tizen> 7 </since_tizen>
267 public LoopingModeType LoopingMode
271 currentStates.loopMode = (LoopingModeType)value;
272 currentStates.changed = true;
274 tlog.Fatal(tag, $"<[{GetId()}] SET loopMode={currentStates.loopMode}>");
275 PropertyMap map = new PropertyMap();
276 map.Add(ImageVisualProperty.LoopingMode, new PropertyValue((int)currentStates.loopMode));
277 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
281 //tlog.Fatal(tag, $"LoopMode get!");
282 PropertyMap map = base.Image;
286 PropertyValue val = map.Find(ImageVisualProperty.LoopingMode);
289 if (val.Get(out ret))
291 //tlog.Fatal(tag, $"gotten LoopMode={ret}");
292 if (ret != (int)currentStates.loopMode && ret > 0)
294 tlog.Fatal(tag, $" [ERROR][{GetId()}](LottieAnimationView) different LoopMode! gotten={ret}, loopMode={currentStates.loopMode}");
296 currentStates.loopMode = (LoopingModeType)ret;
297 return (LoopingModeType)ret;
301 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get loopMode from dali>");
302 return currentStates.loopMode;
307 /// Sets or gets the loop count.
310 /// The minus value means the infinite loop count.
314 /// LottieAnimationView myLottie = new LottieAnimationView();
315 /// myLottie.URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "myLottie.json"; //myLottie.json's total frame is 100 (frame: 0~99)
316 /// NUIApplication.GetDefaultWindow().GetDefaultLayer().Add(myLottie);
317 /// myLottie.LoopCount = -1; //infinite loop
319 /// myLottie.Stop(); //it plays continuously unless Stop() is called
320 /// myLottie.LoopCount = 2;
321 /// myLottie.Play(); //it plays only 2 times and stops automatically
324 /// <since_tizen> 7 </since_tizen>
329 currentStates.changed = true;
330 currentStates.loopCount = value;
331 tlog.Fatal(tag, $"<[{GetId()}]SET currentStates.loopCount={currentStates.loopCount}>");
332 PropertyMap map = new PropertyMap();
333 map.Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount));
334 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
338 //tlog.Fatal(tag, $"LoopCount get!");
339 PropertyMap map = base.Image;
343 PropertyValue val = map.Find(ImageVisualProperty.LoopCount);
346 if (val.Get(out ret))
348 //tlog.Fatal(tag, $"gotten loop count={ret}");
349 if (ret != currentStates.loopCount && ret > 0)
351 tlog.Fatal(tag, $"<[ERROR][{GetId()}](LottieAnimationView) different loop count! gotten={ret}, loopCount={currentStates.loopCount}>");
353 currentStates.loopCount = ret;
354 return currentStates.loopCount;
358 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get LoopCount from dali currentStates.loopCount={currentStates.loopCount}>");
359 return currentStates.loopCount;
364 /// Sets or gets the stop behavior.
366 /// <since_tizen> 7 </since_tizen>
367 public StopBehaviorType StopBehavior
371 currentStates.stopEndAction = (StopBehaviorType)value;
372 currentStates.changed = true;
374 tlog.Fatal(tag, $"<[{GetId()}]SET val={currentStates.stopEndAction}>");
375 PropertyMap map = new PropertyMap();
376 map.Add(ImageVisualProperty.StopBehavior, new PropertyValue((int)currentStates.stopEndAction));
377 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
381 //tlog.Fatal(tag, $"StopBehavior get!");
382 PropertyMap map = base.Image;
386 PropertyValue val = map.Find(ImageVisualProperty.StopBehavior);
389 if (val.Get(out ret))
391 //tlog.Fatal(tag, $"gotten StopBehavior={ret}");
392 if (ret != (int)currentStates.stopEndAction)
394 tlog.Fatal(tag, $"<[ERROR][{GetId()}](LottieAnimationView) different StopBehavior! gotten={ret}, StopBehavior={currentStates.stopEndAction}>");
396 currentStates.stopEndAction = (StopBehaviorType)ret;
397 return (StopBehaviorType)ret;
401 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get StopBehavior from dali>");
402 return currentStates.stopEndAction;
407 /// Whether to redraw the image when the visual is scaled down.
411 /// It is used in the AnimatedVectorImageVisual.The default is true.
413 [EditorBrowsable(EditorBrowsableState.Never)]
414 public bool RedrawInScalingDown
418 currentStates.changed = true;
419 currentStates.redrawInScalingDown = value;
420 tlog.Fatal(tag, $"<[{GetId()}]SET currentStates.redrawInScalingDown={currentStates.redrawInScalingDown}>");
421 PropertyMap map = new PropertyMap();
422 map.Add(ImageVisualProperty.RedrawInScalingDown, new PropertyValue(currentStates.redrawInScalingDown));
423 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
427 PropertyMap map = base.Image;
431 PropertyValue val = map.Find(ImageVisualProperty.RedrawInScalingDown);
434 if (val.Get(out ret))
436 if (ret != currentStates.redrawInScalingDown)
438 tlog.Fatal(tag, $"<[ERROR][{GetId()}](LottieAnimationView) different redrawInScalingDown! gotten={ret}, redrawInScalingDown={currentStates.redrawInScalingDown}>");
440 currentStates.redrawInScalingDown = ret;
441 return currentStates.redrawInScalingDown;
445 Tizen.Log.Error(tag, $"<[ERROR][{GetId()}](LottieAnimationView) Fail to get redrawInScalingDown from dali currentStates.redrawInScalingDown={currentStates.redrawInScalingDown}>");
446 return currentStates.redrawInScalingDown;
454 /// Set the minimum and the maximum frame.
456 /// <param name="minFrame">minimum frame</param>
457 /// <param name="maxFrame">maximum frame</param>
458 /// <since_tizen> 7 </since_tizen>
459 public void SetMinMaxFrame(int minFrame, int maxFrame)
461 tlog.Fatal(tag, $"< [{GetId()}] SetPlayRange({minFrame}, {maxFrame})");
463 currentStates.changed = true;
464 currentStates.framePlayRangeMin = minFrame;
465 currentStates.framePlayRangeMax = maxFrame;
467 PropertyArray array = new PropertyArray();
468 array.PushBack(new PropertyValue(currentStates.framePlayRangeMin));
469 array.PushBack(new PropertyValue(currentStates.framePlayRangeMax));
471 PropertyMap map = new PropertyMap();
472 map.Add(ImageVisualProperty.PlayRange, new PropertyValue(array));
473 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
474 tlog.Fatal(tag, $" [{GetId()}] currentStates.min:({currentStates.framePlayRangeMin}, max:{currentStates.framePlayRangeMax})>");
480 /// <since_tizen> 7 </since_tizen>
481 public new void Play()
483 tlog.Fatal(tag, $"<[{GetId()}] Play()");
486 tlog.Fatal(tag, $"[{GetId()}]>");
492 /// <since_tizen> 7 </since_tizen>
493 public new void Pause()
495 tlog.Fatal(tag, $"<[{GetId()}] Pause()>");
498 tlog.Fatal(tag, $"[{GetId()}]>");
504 /// <since_tizen> 7 </since_tizen>
505 public new void Stop()
507 tlog.Fatal(tag, $"<[{GetId()}] Stop()");
510 tlog.Fatal(tag, $"[{GetId()}]>");
514 /// Get the list of layers' information such as the start frame and the end frame in the Lottie file.
516 /// <returns>List of Tuple (string of layer name, integer of start frame, integer of end frame)</returns>
517 /// <since_tizen> 7 </since_tizen>
518 public List<Tuple<string, int, int>> GetContentInfo()
520 tlog.Fatal(tag, $"<");
521 if (currentStates.contentInfo != null)
523 return currentStates.contentInfo;
526 PropertyMap imageMap = base.Image;
527 PropertyMap contentMap = new PropertyMap();
528 if (imageMap != null)
530 PropertyValue val = imageMap.Find(ImageVisualProperty.ContentInfo);
533 if (val.Get(contentMap))
535 currentStates.contentInfo = new List<Tuple<string, int, int>>();
536 for (uint i = 0; i < contentMap.Count(); i++)
538 string key = contentMap.GetKeyAt(i).StringKey;
539 PropertyArray arr = new PropertyArray();
540 contentMap.GetValue(i).Get(arr);
543 int startFrame, endFrame;
544 arr.GetElementAt(0).Get(out startFrame);
545 arr.GetElementAt(1).Get(out endFrame);
547 tlog.Fatal(tag, $"[{i}] layer name={key}, startFrame={startFrame}, endFrame={endFrame}");
549 Tuple<string, int, int> item = new Tuple<string, int, int>(key, startFrame, endFrame);
551 currentStates.contentInfo?.Add(item);
557 tlog.Fatal(tag, $">");
558 return currentStates.contentInfo;
562 /// A marker has its start frame and end frame.
563 /// Animation will play between the start frame and the end frame of the marker if one marker is specified.
564 /// 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. *
566 /// <param name="marker1">First marker</param>
567 /// <param name="marker2">Second marker</param>
568 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
569 [EditorBrowsable(EditorBrowsableState.Never)]
570 public void SetMinMaxFrameByMarker(string marker1, string marker2 = null)
572 tlog.Fatal(tag, $"< [{GetId()}] SetMinMaxFrameByMarker({marker1}, {marker2})");
574 currentStates.changed = true;
575 currentStates.mark1 = marker1;
576 currentStates.mark2 = marker2;
578 PropertyArray array = new PropertyArray();
579 array.PushBack(new PropertyValue(currentStates.mark1));
582 array.PushBack(new PropertyValue(currentStates.mark2));
585 PropertyMap map = new PropertyMap();
586 map.Add(ImageVisualProperty.PlayRange, new PropertyValue(array));
587 DoAction(ImageView.Property.IMAGE, (int)actionType.updateProperty, new PropertyValue(map));
588 tlog.Fatal(tag, $" [{GetId()}] currentStates.mark1:{currentStates.mark1}, mark2:{currentStates.mark2} >");
594 /// <returns>Tuple of Min and Max frames</returns>
595 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
596 [EditorBrowsable(EditorBrowsableState.Never)]
597 public Tuple<int, int> GetMinMaxFrame()
599 tlog.Fatal(tag, $"< [{GetId()}] GetMinMaxFrame()! total frame={currentStates.totalFrame}");
601 PropertyMap map = Image;
604 PropertyValue val = map.Find(ImageVisualProperty.PlayRange);
607 PropertyArray array = new PropertyArray();
610 uint cnt = array.Count();
611 int item1 = -1, item2 = -1;
612 for (uint i = 0; i < cnt; i++)
614 PropertyValue v = array.GetElementAt(i);
616 if (v.Get(out intRet))
618 tlog.Fatal(tag, $"Got play range of string [{i}]: {intRet}");
630 Tizen.Log.Error("NUI", $"[ERR] fail to get play range from dali! case#1");
633 tlog.Fatal(tag, $" [{GetId()}] GetMinMaxFrame(min:{item1}, max:{item2})! >");
634 return new Tuple<int, int>(item1, item2);
638 Tizen.Log.Error("NUI", $"[ERR] fail to get play range from dali! case#2");
639 return new Tuple<int, int>(-1, -1);
644 #region Event, Enum, Struct, ETC
646 /// Animation finished event.
648 /// <since_tizen> 7 </since_tizen>
649 public event EventHandler Finished
653 if (finishedEventHandler == null)
655 tlog.Fatal(tag, $"<[{GetId()}] Finished eventhandler added>");
656 visualEventSignalCallback = onVisualEventSignal;
657 VisualEventSignal().Connect(visualEventSignalCallback);
659 finishedEventHandler += value;
663 tlog.Fatal(tag, $"<[{GetId()}] Finished eventhandler removed>");
664 finishedEventHandler -= value;
665 if (finishedEventHandler == null && visualEventSignalCallback != null)
667 VisualEventSignal().Disconnect(visualEventSignalCallback);
673 /// Enumeration for what state the vector animation is in
675 /// <since_tizen> 7 </since_tizen>
676 public enum PlayStateType
681 /// <since_tizen> 7 </since_tizen>
684 /// Vector Animation has stopped
686 /// <since_tizen> 7 </since_tizen>
689 /// The vector animation is playing
691 /// <since_tizen> 7 </since_tizen>
694 /// The vector animation is paused
696 /// <since_tizen> 7 </since_tizen>
701 /// Enumeration for what to do when the animation is stopped.
703 /// <since_tizen> 7 </since_tizen>
704 public enum StopBehaviorType
707 /// When the animation is stopped, the current frame is shown.
709 /// <since_tizen> 7 </since_tizen>
712 /// When the animation is stopped, the min frame (first frame) is shown.
714 /// <since_tizen> 7 </since_tizen>
717 /// When the animation is stopped, the max frame (last frame) is shown.
719 /// <since_tizen> 7 </since_tizen>
724 /// Enumeration for what looping mode is in.
726 /// <since_tizen> 7 </since_tizen>
727 public enum LoopingModeType
730 /// When the animation arrives at the end in looping mode, the animation restarts from the beginning.
732 /// <since_tizen> 7 </since_tizen>
735 /// When the animation arrives at the end in looping mode, the animation reverses direction and runs backwards again.
737 /// <since_tizen> 7 </since_tizen>
740 #endregion Event, Enum, Struct, ETC
744 internal class VisualEventSignalArgs : EventArgs
746 public int VisualIndex
758 internal event EventHandler<VisualEventSignalArgs> VisualEvent
762 if (visualEventSignalHandler == null)
764 visualEventSignalCallback = onVisualEventSignal;
765 VisualEventSignal().Connect(visualEventSignalCallback);
767 visualEventSignalHandler += value;
771 visualEventSignalHandler -= value;
772 if (visualEventSignalHandler == null && VisualEventSignal().Empty() == false)
774 VisualEventSignal().Disconnect(visualEventSignalCallback);
779 internal void EmitVisualEventSignal(int visualIndex, int signalId)
781 VisualEventSignal().Emit(this, visualIndex, signalId);
784 internal VisualEventSignal VisualEventSignal()
786 VisualEventSignal ret = new VisualEventSignal(Interop.VisualEventSignal.NewWithView(View.getCPtr(this)), false);
787 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
794 private struct states
798 internal int loopCount;
799 internal LoopingModeType loopMode;
800 internal StopBehaviorType stopEndAction;
801 internal int framePlayRangeMin;
802 internal int framePlayRangeMax;
803 internal bool changed;
804 internal int totalFrame;
805 internal float scale;
806 internal PlayStateType playState;
807 internal List<Tuple<string, int, int>> contentInfo;
808 internal string mark1, mark2;
809 internal bool redrawInScalingDown;
811 private states currentStates;
813 private enum actionType
822 private struct DevelVisual
826 AnimatedGradient = Visual.Type.AnimatedImage + 1,
827 AnimatedVectorImage = Visual.Type.AnimatedImage + 2,
831 private const string tag = "NUITEST";
832 private event EventHandler finishedEventHandler;
834 private void OnFinished()
836 tlog.Fatal(tag, $"<[{GetId()}] OnFinished()>");
837 finishedEventHandler?.Invoke(this, null);
840 private void onVisualEventSignal(IntPtr targetView, int visualIndex, int signalId)
844 if (targetView != IntPtr.Zero)
846 View v = Registry.GetManagedBaseHandleFromNativePtr(targetView) as View;
849 tlog.Fatal(tag, $"targetView is not null! name={v.Name}");
853 tlog.Fatal(tag, $"target is something created from dali");
856 VisualEventSignalArgs e = new VisualEventSignalArgs();
857 e.VisualIndex = visualIndex;
858 e.SignalId = signalId;
859 visualEventSignalHandler?.Invoke(this, e);
861 tlog.Fatal(tag, $"<[{GetId()}] onVisualEventSignal()! visualIndex={visualIndex}, signalId={signalId}>");
864 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
865 private delegate void VisualEventSignalCallbackType(IntPtr targetView, int visualIndex, int signalId);
867 private VisualEventSignalCallbackType visualEventSignalCallback;
868 private EventHandler<VisualEventSignalArgs> visualEventSignalHandler;
870 private void debugPrint()
872 tlog.Fatal(tag, $"===================================");
873 tlog.Fatal(tag, $"<[{GetId()}] get currentStates : url={currentStates.url}, loopCount={currentStates.loopCount}, \nframePlayRangeMin/Max({currentStates.framePlayRangeMin},{currentStates.framePlayRangeMax}) ");
874 tlog.Fatal(tag, $" get from Property : StopBehavior={StopBehavior}, LoopMode={LoopingMode}, LoopCount={LoopCount}, PlayState={PlayState}");
875 tlog.Fatal(tag, $" RedrawInScalingDown={RedrawInScalingDown} >");
876 tlog.Fatal(tag, $"===================================");
882 /// A class containing frame informations for a LottieAnimationView.
884 [EditorBrowsable(EditorBrowsableState.Never)]
885 public class LottieFrameInfo : ICloneable
888 /// Creates a new instance with a playing range.
890 [EditorBrowsable(EditorBrowsableState.Never)]
891 public LottieFrameInfo(int startFrame, int endFrame)
893 StartFrame = startFrame;
898 /// Creates a new instance with a still image frame.
900 [EditorBrowsable(EditorBrowsableState.Never)]
901 public LottieFrameInfo(int stillImageFrame) : this(stillImageFrame, stillImageFrame)
906 /// Create a new instance from a pair notation.
908 [EditorBrowsable(EditorBrowsableState.Never)]
909 public static implicit operator LottieFrameInfo((int, int) pair)
911 return new LottieFrameInfo(pair.Item1, pair.Item2);
915 /// Create a new instance from an int value.
917 [EditorBrowsable(EditorBrowsableState.Never)]
918 public static implicit operator LottieFrameInfo(int stillImageFrame)
920 return new LottieFrameInfo(stillImageFrame);
924 /// Create a new instance from string.
925 /// Possible input : "0, 10", "10"
927 [EditorBrowsable(EditorBrowsableState.Never)]
928 public static implicit operator LottieFrameInfo(string pair)
935 string[] parts = pair.Split(',');
936 if (parts.Length == 1)
938 return new LottieFrameInfo(Int32.Parse(parts[0].Trim()));
940 else if (parts.Length == 2)
942 return new LottieFrameInfo(Int32.Parse(parts[0].Trim()), Int32.Parse(parts[1].Trim()));
945 Tizen.Log.Error("NUI", $"Can not convert string {pair} to LottieFrameInfo");
950 /// The start frame of the lottie animation.
952 [EditorBrowsable(EditorBrowsableState.Never)]
953 public int StartFrame { get; }
956 /// The end frame of the lottie animation.
958 [EditorBrowsable(EditorBrowsableState.Never)]
959 public int EndFrame { get; }
962 /// Create LottieFrameInfo struct with animation range information
964 [EditorBrowsable(EditorBrowsableState.Never)]
965 public static LottieFrameInfo CreateAnimationRange(int startFrame, int endFrame)
967 return new LottieFrameInfo(startFrame, endFrame);
971 /// Create LottieFrameInfo struct with still image information
973 [EditorBrowsable(EditorBrowsableState.Never)]
974 public static LottieFrameInfo CreateStillImage(int stillImageFrame)
976 return new LottieFrameInfo(stillImageFrame, stillImageFrame);
981 /// Whether this LottieFrameInfo represents one frame or more.
983 [EditorBrowsable(EditorBrowsableState.Never)]
984 public bool IsStillImage()
986 return StartFrame == EndFrame;
991 /// Play specified LottieAnimationView with this frame information.
993 /// <param name="lottieView">The target LottieAnimationView to play.</param>
994 /// <param name="noPlay">Whether go direct to the EndFrame. It is false by default.</param>
995 [EditorBrowsable(EditorBrowsableState.Never)]
996 public void Show(LottieAnimationView lottieView, bool noPlay = false)
998 if (!BeReadyToShow(lottieView))
1003 lottieView.SetMinMaxFrame(StartFrame, Math.Min(EndFrame, lottieView.TotalFrame - 1));
1005 if (IsStillImage() || noPlay)
1007 lottieView.CurrentFrame = EndFrame;
1011 lottieView.CurrentFrame = StartFrame;
1017 [EditorBrowsable(EditorBrowsableState.Never)]
1018 public object Clone() => new LottieFrameInfo(StartFrame, EndFrame);
1020 private bool BeReadyToShow(LottieAnimationView lottieView)
1022 // Validate input lottieView
1023 if (null == lottieView || lottieView.PlayState == LottieAnimationView.PlayStateType.Invalid)
1028 // Stop if it was playing
1029 if (lottieView.PlayState == LottieAnimationView.PlayStateType.Playing)