From 882912bf7e39a2660d2e29bf8801b8b57865aa2a Mon Sep 17 00:00:00 2001 From: dongsug-song <35130733+dongsug-song@users.noreply.github.com> Date: Fri, 28 Jun 2019 17:28:20 +0900 Subject: [PATCH] [NUI] Add AnimatedVectorImageView (#908) --- .../BaseComponents/AnimatedVectorImageView.cs | 606 +++++++++++++++ .../BaseComponents/VectorAnimationView.cs | 687 +++--------------- 2 files changed, 727 insertions(+), 566 deletions(-) create mode 100755 src/Tizen.NUI/src/public/BaseComponents/AnimatedVectorImageView.cs diff --git a/src/Tizen.NUI/src/public/BaseComponents/AnimatedVectorImageView.cs b/src/Tizen.NUI/src/public/BaseComponents/AnimatedVectorImageView.cs new file mode 100755 index 000000000..5467107a7 --- /dev/null +++ b/src/Tizen.NUI/src/public/BaseComponents/AnimatedVectorImageView.cs @@ -0,0 +1,606 @@ +/* + * Copyright(c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +using global::System; +using global::System.Runtime.InteropServices; +using System.ComponentModel; +using tizenlog = Tizen.Log; + +namespace Tizen.NUI.BaseComponents +{ + /// + /// AnimatedVectorImageView renders an animated vector image + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public class AnimatedVectorImageView : ImageView + { + #region Constructor, Distructor, Dispose + /// + /// AnimatedVectorImageView + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public AnimatedVectorImageView() : base() + { + NUILog.Debug($"AnimatedVectorImageView() constructor!"); + currentStates.url = ""; + currentStates.frame = -1; + currentStates.loopCount = 0; + currentStates.loopMode = LoopModes.Forward; + //currentStates.stopEndAction = EndActions.Cancel; + currentStates.framePlayRangeMin = -1; + currentStates.framePlayRangeMax = -1; + currentStates.changed = false; + currentStates.totalFrame = -1; + currentStates.scale = 1.0f; + } + + /// + /// AnimatedVectorImageView(float scale) + /// + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public AnimatedVectorImageView(float scale) : this() + { + currentStates.scale = scale; + } + + /// + /// Dispose(DisposeTypes type) + /// + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + protected override void Dispose(DisposeTypes type) + { + if (disposed) + { + return; + } + + NUILog.Debug($"Dispose(type={type})!"); + + if (type == DisposeTypes.Explicit) + { + //Called by User + //Release your own managed resources here. + //You should release all of your own disposable objects here. + } + + //Release your own unmanaged resources here. + //You should not access any managed member here except static instance. + //because the execution order of Finalizes is non-deterministic. + + //disconnect event signal + if (finishedEventHandler != null && visualEventSignalCallback != null) + { + VisualEventSignal().Disconnect(visualEventSignalCallback); + finishedEventHandler = null; + NUILog.Debug($"disconnect event signal"); + } + + base.Dispose(type); + } + #endregion Constructor, Distructor, Dispose + + + #region Property + /// + /// URL + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public string URL + { + set + { + NUILog.Debug($"URL set! value={value}"); + string ret = (value == null ? "" : value); + currentStates.url = ret; + currentStates.changed = true; + + PropertyMap map = new PropertyMap(); + map.Add(Visual.Property.Type, new PropertyValue((int)DevelVisual.Type.AnimatedVectorImage)) + .Add(ImageVisualProperty.URL, new PropertyValue(currentStates.url)) + .Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount)); + //.Add(ImageVisualProperty.StopEndAction, new PropertyValue((int)currentStates.stopEndAction)) + //.Add(ImageVisualProperty.LoopMode, new PropertyValue((int)currentStates.loopMode)); + Image = map; + } + get + { + string ret = ResourceUrl; + NUILog.Debug($"URL get! base ret={ret}, Name={Name}"); + PropertyMap map = Image; + if (map != null) + { + PropertyValue val = map.Find(ImageVisualProperty.URL); + if (val != null) + { + if (val.Get(out ret)) + { + NUILog.Debug($"gotten url={ret}"); + return ret; + } + } + } + tizenlog.Error(tag, "[ERROR] fail to get URL from dali"); + return ret; + } + } + + /// + /// The playing state + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public PlayStateType PlayState + { + get + { + var ret = -1; + PropertyMap map = Image; + if (map != null) + { + PropertyValue val = map.Find((int)DevelVisual.Type.AnimatedVectorImage); + if (val != null) + { + if (val.Get(out ret)) + { + return (PlayStateType)ret; + } + } + } + tizenlog.Error(tag, $"[ERROR] fail to get PlayState from dali"); + return (PlayStateType)ret; + } + } + + /// + /// The number of total frame + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public int TotalFrameNumber + { + get + { + int ret = -1; + PropertyMap map = Image; + if (map != null) + { + PropertyValue val = map.Find(ImageVisualProperty.TotalFrameNumber); + if (val != null) + { + if (val.Get(out ret)) + { + NUILog.Debug($"TotalFrameNumber get! ret={ret}"); + currentStates.totalFrame = ret; + return ret; + } + } + } + tizenlog.Error(tag, $"[ERROR] fail to get TotalFrameNumber from dali"); + return ret; + } + } + + /// + /// CurrentFrameNumber + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public int CurrentFrameNumber + { + set + { + currentStates.frame = value; + NUILog.Debug($"set CurrentFrameNumber={currentStates.frame}"); + DoAction(vectorImageVisualIndex, (int)actionType.jumpTo, new PropertyValue(currentStates.frame)); + } + get + { + int ret = 0; + PropertyMap map = Image; + if (map != null) + { + PropertyValue val = map.Find(ImageVisualProperty.CurrentFrameNumber); + if (val != null) + { + if (val.Get(out ret)) + { + NUILog.Debug($"CurrentFrameNumber get! val={ret}"); + return ret; + } + } + } + tizenlog.Error(tag, $"[ERROR] fail to get CurrentFrameNumber from dali!! ret={ret}"); + return ret; + } + } + + /// + /// Loop Mode of animation. + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public LoopModes LoopMode + { + set + { + currentStates.loopMode = (LoopModes)value; + currentStates.changed = true; + + + NUILog.Debug($"LoopMode set val={currentStates.loopMode}"); + //PropertyMap map = new PropertyMap(); + //map.Add(ImageVisualProperty.LoopMode, new PropertyValue((int)currentStates.loopMode)); + //DoAction(vectorImageVisualIndex, (int)actionType.updateProperty, new PropertyValue(map)); + } + get + { + NUILog.Debug($"LoopMode get!"); + PropertyMap map = base.Image; + var ret = 0; + //if (map != null) + //{ + // PropertyValue val = map.Find(ImageVisualProperty.LoopMode); + // if (val != null) + // { + // if (val.Get(out ret)) + // { + // NUILog.Debug($"gotten LoopMode={ret}"); + // if (ret != (int)currentStates.loopMode && ret > 0) + // { + // NUILog.Debug($"different LoopMode! gotten={ret}, loopMode={currentStates.loopMode}"); + // return (int)currentStates.loopMode; + // } + // return ret; + // } + // } + //} + tizenlog.Error(tag, "[ERROR] fail to get loopMode from dali"); + return (LoopModes)ret; + } + } + + /// + /// LoopCount + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public int LoopCount + { + set + { + currentStates.changed = true; + currentStates.loopCount = value; + NUILog.Debug($"LoopCount set! currentStates.loopCount={currentStates.loopCount}"); + PropertyMap map = new PropertyMap(); + map.Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount)); + DoAction(vectorImageVisualIndex, (int)actionType.updateProperty, new PropertyValue(map)); + } + get + { + NUILog.Debug($"LoopCount get!"); + PropertyMap map = base.Image; + var ret = 0; + if (map != null) + { + PropertyValue val = map.Find(ImageVisualProperty.LoopCount); + if (val != null) + { + if (val.Get(out ret)) + { + NUILog.Debug($"gotten loop count={ret}"); + if (ret != currentStates.loopCount && ret > 0) + { + NUILog.Debug($"[ERR] different loop count! gotten={ret}, loopCount={currentStates.loopCount}"); + } + return currentStates.loopCount; + } + } + } + tizenlog.Error(tag, $"[ERROR] fail to get LoopCount from dali currentStates.loopCount={currentStates.loopCount}"); + return currentStates.loopCount; + } + } + #endregion Property + + + #region Method + /// + /// SetPlayRange(int startFrame, int endFrame) + /// + /// + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public void SetPlayRange(int startFrame, int endFrame) + { + NUILog.Debug($"SetPlayRange(startFrame={startFrame}, endFrame={endFrame})"); + + currentStates.changed = true; + currentStates.framePlayRangeMin = startFrame; + currentStates.framePlayRangeMax = endFrame; + + PropertyArray array = new PropertyArray(); + array.PushBack(new PropertyValue(currentStates.framePlayRangeMin)); + array.PushBack(new PropertyValue(currentStates.framePlayRangeMax)); + + PropertyMap map = new PropertyMap(); + map.Add(ImageVisualProperty.PlayRange, new PropertyValue(array)); + DoAction(vectorImageVisualIndex, (int)actionType.updateProperty, new PropertyValue(map)); + NUILog.Debug($"currentStates.framePlayRangeMin={currentStates.framePlayRangeMin}, currentStates.framePlayRangeMax={currentStates.framePlayRangeMax})"); + } + + /// + /// Play Animation. + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public new void Play() + { + NUILog.Debug($"Play() called!"); + debugPrint(); + base.Play(); + } + + /// + /// Pause Animation. + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public new void Pause() + { + NUILog.Debug($"Pause() called!"); + debugPrint(); + base.Pause(); + } + + /// + /// Stop Animation. + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public new void Stop() + { + NUILog.Debug($"Stop()!"); + debugPrint(); + base.Stop(); + } + #endregion Method + + + #region Event, Enum, Struct, ETC + /// + /// Animation finished event + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public event EventHandler Finished + { + add + { + if (finishedEventHandler == null) + { + NUILog.Debug($"Finished()! add!"); + visualEventSignalCallback = onVisualEventSignal; + VisualEventSignal().Connect(visualEventSignalCallback); + } + finishedEventHandler += value; + } + remove + { + NUILog.Debug($"Finished()! remove!"); + finishedEventHandler -= value; + if (finishedEventHandler == null && visualEventSignalCallback != null) + { + VisualEventSignal().Disconnect(visualEventSignalCallback); + } + } + } + + /// + /// Loop mode + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public enum LoopModes + { + /// + /// Forward + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + Forward = 1, + /// + /// Reverse + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + Backward = 2 + } + + /// + /// Enumeration for what state the vector animation is in + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + public enum PlayStateType + { + /// + /// Invalid + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + Invalid = -1, + /// + /// Vector Animation has stopped + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + Stopped = 0, + /// + /// The vector animation is playing + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + Playing = 1, + /// + /// The vector animation is paused + /// + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + Paused = 2 + } + #endregion Event, Enum, Struct, ETC + + + #region Internal + internal class VisualEventSignalArgs : EventArgs + { + public int VisualIndex + { + set; + get; + } + public int SignalId + { + set; + get; + } + } + + internal event EventHandler VisualEvent + { + add + { + if (visualEventSignalHandler == null) + { + visualEventSignalCallback = onVisualEventSignal; + VisualEventSignal().Connect(visualEventSignalCallback); + } + visualEventSignalHandler += value; + } + remove + { + visualEventSignalHandler -= value; + if (visualEventSignalHandler == null && VisualEventSignal().Empty() == false) + { + VisualEventSignal().Disconnect(visualEventSignalCallback); + } + } + } + + internal void EmitVisualEventSignal(int visualIndex, int signalId) + { + VisualEventSignal().Emit(this, visualIndex, signalId); + } + + internal VisualEventSignal VisualEventSignal() + { + VisualEventSignal ret = new VisualEventSignal(Interop.VisualEventSignal.NewWithView(View.getCPtr(this)), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + #endregion Internal + + + #region Private + private struct states + { + internal string url; + internal int frame; + internal int loopCount; + internal LoopModes loopMode; + //internal EndActions stopEndAction; + internal int framePlayRangeMin; + internal int framePlayRangeMax; + internal bool changed; + internal int totalFrame; + internal float scale; + }; + private states currentStates; + + private enum actionType + { + play, + pause, + stop, + jumpTo, + updateProperty, + }; + + private struct DevelVisual + { + internal enum Type + { + AnimatedGradient = Visual.Type.AnimatedImage + 1, + AnimatedVectorImage = Visual.Type.AnimatedImage + 2, + } + } + + private const string tag = "NUI"; + private const int vectorImageVisualIndex = 10000000 + 1000 + 2; + private event EventHandler finishedEventHandler; + + private void OnFinished() + { + finishedEventHandler?.Invoke(this, null); + } + + private void onVisualEventSignal(IntPtr targetView, int visualIndex, int signalId) + { + OnFinished(); + + if (targetView != IntPtr.Zero) + { + View v = Registry.GetManagedBaseHandleFromNativePtr(targetView) as View; + if (v != null) + { + NUILog.Debug($"targetView is not null! name={v.Name}"); + } + else + { + NUILog.Debug($"target is something created from dali"); + } + } + VisualEventSignalArgs e = new VisualEventSignalArgs(); + e.VisualIndex = visualIndex; + e.SignalId = signalId; + visualEventSignalHandler?.Invoke(this, e); + + NUILog.Debug($"@@ onVisualEventSignal()! visualIndex={visualIndex}, signalId={signalId}"); + } + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate void VisualEventSignalCallbackType(IntPtr targetView, int visualIndex, int signalId); + + private VisualEventSignalCallbackType visualEventSignalCallback; + private EventHandler visualEventSignalHandler; + + private void debugPrint() + { + NUILog.Debug($"======= currentStates"); + NUILog.Debug($"url={currentStates.url}, loopCount={currentStates.loopCount}, framePlayRangeMin={currentStates.framePlayRangeMin}, framePlayRangeMax={currentStates.framePlayRangeMax} \n"); + } + #endregion Private + } +} diff --git a/src/Tizen.NUI/src/public/BaseComponents/VectorAnimationView.cs b/src/Tizen.NUI/src/public/BaseComponents/VectorAnimationView.cs index af616972a..5d95c5c6b 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/VectorAnimationView.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/VectorAnimationView.cs @@ -16,18 +16,16 @@ */ using global::System; -using global::System.Runtime.InteropServices; using System.ComponentModel; -using tizenlog = Tizen.Log; namespace Tizen.NUI.BaseComponents { /// - /// AnimatedVectorImageView renders an animated vector image + /// VectorAnimationView is a class for displaying a vector resource. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - public class VectorAnimationViewTBD : ImageView + public class VectorAnimationViewTBD : AnimatedVectorImageView { #region Constructor, Distructor, Dispose /// @@ -37,32 +35,16 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public VectorAnimationViewTBD() : base() { - NUILog.Debug($"AnimatedVectorImageView() constructor!"); - //default value in NUI level - currentStates.url = ""; - currentStates.frame = 0; - currentStates.loopCount = 0; - currentStates.repeatMode = RepeatModes.Restart; - currentStates.stopEndAction = EndActions.Cancel; - currentStates.framePlayRangeMin = -1; - currentStates.framePlayRangeMax = -1; - currentStates.changed = false; - currentStates.totalFrame = -1; - currentStates.scale = 1.0f; } /// /// Construct VectorAnimationView. /// /// Set scaling factor for Vector Animation, while creating. - /// - /// Throw API implementation is pending - /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - public VectorAnimationViewTBD(float scale) : base() + public VectorAnimationViewTBD(float scale) : base(scale) { - currentStates.scale = scale; } /// @@ -77,7 +59,6 @@ namespace Tizen.NUI.BaseComponents { return; } - NUILog.Debug($"Dispose(type={type})!"); if (type == DisposeTypes.Explicit) @@ -91,17 +72,9 @@ namespace Tizen.NUI.BaseComponents //You should not access any managed member here except static instance. //because the execution order of Finalizes is non-deterministic. - //disconnect event signal! - if (finishedEventHandler != null && visualEventSignalCallback != null) - { - VisualEventSignal().Disconnect(visualEventSignalCallback); - finishedEventHandler = null; - NUILog.Debug($"disconnect event signal!!!!"); - } - base.Dispose(type); } - #endregion + #endregion Constructor, Distructor, Dispose #region Property @@ -114,95 +87,36 @@ namespace Tizen.NUI.BaseComponents { set { - NUILog.Debug($"URL set! value={value}"); - string ret = (value == null ? "" : value); - currentStates.url = ret; - currentStates.changed = true; - - PropertyMap map = new PropertyMap(); - map.Add(Visual.Property.Type, new PropertyValue((int)DevelVisual.Type.AnimatedVectorImage)) - .Add(ImageVisualProperty.URL, new PropertyValue(currentStates.url)) - .Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount)); - //.Add(ImageVisualProperty.StopEndAction, new PropertyValue((int)currentStates.stopEndAction)) - //.Add(ImageVisualProperty.RepeatMode, new PropertyValue((int)currentStates.repeatMode)); - Image = map; - } - get - { - string ret = ResourceUrl; - NUILog.Debug($"URL get! base resource mUrl={ret}, name={Name}"); - PropertyMap map = Image; - if (map != null) - { - PropertyValue val = map.Find(ImageVisualProperty.URL); - if (val != null) - { - if (val.Get(out ret)) - { - NUILog.Debug($"gotten url={ret}"); - return ret; - } - } - } - tizenlog.Error(tag, "[ERROR] fail to get ResourceUrl from dali"); - return ret; - } - } - - /// - /// The playing state - /// - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - public PlayStateType PlayState - { - get - { - var ret = -1; - PropertyMap map = Image; - if (map != null) + if (value == mResourceURL) { - PropertyValue val = map.Find((int)DevelVisual.Type.AnimatedVectorImage); - if (val != null) - { - if (val.Get(out ret)) - { - return (PlayStateType)ret; - } - } + NUILog.Debug($"set same URL! just return!"); + return; } - tizenlog.Error(tag, $"[ERROR] fail to get PlayState from dali"); - return (PlayStateType)ret; + NUILog.Debug($"Object : {GetId()} URL : {ResourceURL} New URL: {value}"); + mResourceURL = (value == null) ? "" : value; + URL = mResourceURL; + mIsMinMaxSet = false; } + get => mResourceURL; } /// - /// The number of total frame + /// RepeatCount of animation. + /// The repeat count is 0 by default. + /// If the RepeatCount is 0, the animation is never repeated. + /// If the RepeatCount is greater than 0, the repeat mode will be taken into account. + /// If RepeatCount is -1, animation is infinite loops. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - public int TotalFrameNumber + public int RepeatCount { - get + set { - int ret = -1; - PropertyMap map = Image; - if (map != null) - { - PropertyValue val = map.Find(ImageVisualProperty.TotalFrameNumber); - if (val != null) - { - if (val.Get(out ret)) - { - NUILog.Debug($"TotalFrameNumber get! ret={ret}"); - currentStates.totalFrame = ret; - return ret; - } - } - } - tizenlog.Error(tag, $"[ERROR] fail to get TotalFrameNumber from dali"); - return ret; + mRepeatCount = (value < -1) ? -1 : value; + LoopCount = mRepeatCount; } + get => mRepeatCount; } /// @@ -215,29 +129,29 @@ namespace Tizen.NUI.BaseComponents { set { - currentStates.frame = value; - NUILog.Debug($"set CurrentFrame={currentStates.frame}"); - DoAction(vectorImageVisualIndex, (int)actionType.jumpTo, new PropertyValue(currentStates.frame)); - } - get - { - int ret = -1; - PropertyMap map = Image; - if (map != null) + if (mResourceURL == null || mResourceURL == String.Empty) + { + throw new InvalidOperationException("Resource Url not yet Set"); + } + + mFrameCount = TotalFrameNumber; + + if (value < 0) + { + value = 0; + } + else if (value >= mFrameCount) { - PropertyValue val = map.Find(ImageVisualProperty.CurrentFrameNumber); - if (val != null) - { - if (val.Get(out ret)) - { - NUILog.Debug($"CurrentFrame get! val={ret}"); - return ret; - } - } + value = mFrameCount - 1; } - tizenlog.Error(tag, $"[ERROR] fail to get CurrentFrame from dali"); - return ret; + NUILog.Debug($"Object : {GetId()} URL : {ResourceURL} New Frame: {value}, Old Frame : {mCurrentFrame}"); + mCurrentFrame = value; + AnimationState = AnimationStates.Paused; + + SetPlayRange(mCurrentFrame, mCurrentFrame); + CurrentFrameNumber = mCurrentFrame; } + get => mCurrentFrame; } /// @@ -249,40 +163,10 @@ namespace Tizen.NUI.BaseComponents { set { - currentStates.repeatMode = (RepeatModes)value; - currentStates.changed = true; - - - NUILog.Debug($"RepeatMode set val={currentStates.repeatMode}"); - //PropertyMap map = new PropertyMap(); - //map.Add(ImageVisualProperty.RepeatMode, new PropertyValue((int)currentStates.repeatMode)); - //DoAction(vectorImageVisualIndex, (int)actionType.updateProperty, new PropertyValue(map)); - } - get - { - NUILog.Debug($"RepeatMode get!"); - PropertyMap map = base.Image; - var ret = 0; - //if (map != null) - //{ - // PropertyValue val = map.Find(ImageVisualProperty.RepeatMode); - // if (val != null) - // { - // if (val.Get(out ret)) - // { - // NUILog.Debug($"gotten RepeatMode={ret}"); - // if (ret != (int)currentStates.repeatMode && ret > 0) - // { - // NUILog.Debug($"different RepeatMode! gotten={ret}, repeatMode={currentStates.repeatMode}"); - // return (int)currentStates.repeatMode; - // } - // return ret; - // } - // } - //} - tizenlog.Error(tag, "[ERROR] fail to get repeatMode from dali"); - return (RepeatModes)ret; + mRepeatMode = value; + LoopMode = (AnimatedVectorImageView.LoopModes)mRepeatMode; } + get => mRepeatMode; } /// @@ -295,62 +179,7 @@ namespace Tizen.NUI.BaseComponents private set; get; } - - /// - /// RepeatCount of animation. - /// The repeat count is 0 by default. - /// If the RepeatCount is 0, the animation is never repeated. - /// If the RepeatCount is greater than 0, the repeat mode will be taken into account. - /// If RepeatCount is -1, animation is infinite loops. - /// - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - public int RepeatCount - { - set - { - if (value < 0) - { - currentStates.loopCount = -1; - } - else - { - currentStates.loopCount = value; - } - currentStates.changed = true; - - NUILog.Debug($"LoopCount set val={currentStates.loopCount}"); - PropertyMap map = new PropertyMap(); - map.Add(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount)); - DoAction(vectorImageVisualIndex, (int)actionType.updateProperty, new PropertyValue(map)); - } - get - { - NUILog.Debug($"LoopCount get!"); - PropertyMap map = base.Image; - var ret = 0; - if (map != null) - { - PropertyValue val = map.Find(ImageVisualProperty.LoopCount); - if (val != null) - { - if (val.Get(out ret)) - { - NUILog.Debug($"gotten loop count={ret}"); - if (ret != currentStates.loopCount && ret > 0) - { - NUILog.Debug($"different loop count! gotten={ret}, loopCount={currentStates.loopCount}"); - return currentStates.loopCount; - } - return (ret < 0 ? ret : ret - 1); - } - } - } - tizenlog.Error(tag, "[ERROR] fail to get LoopCount from dali"); - return ret; - } - } - #endregion + #endregion Property #region Method @@ -363,17 +192,28 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public void SetMinAndMaxFrame(int minFrame, int maxFrame) { - var mMinFrame = (minFrame) > 0 ? minFrame : 0; - var mMaxFrame = (maxFrame) > 0 ? maxFrame : 0; + mMinFrame = (minFrame) > 0 ? minFrame : 0; + mMaxFrame = (maxFrame) > 0 ? maxFrame : 0; + mIsMinMaxSet = true; + mFrameCount = TotalFrameNumber; + + if (mMinFrame >= mFrameCount) + { + mMinFrame = mFrameCount - 1; + } + + if (mMaxFrame >= mFrameCount) + { + mMaxFrame = mFrameCount - 1; + } if (mMinFrame > mMaxFrame) { return; } - NUILog.Debug($"SetMinAndMaxFrame()! minFrame={mMinFrame}, maxFrame={mMaxFrame}"); + NUILog.Debug($"SetMinAndMaxFrame({mMinFrame}, {mMaxFrame})"); - Vector2 range = new Vector2((float)mMinFrame, (float)mMaxFrame); - SetFramePlayRange(range); + SetPlayRange(mMinFrame, mMaxFrame); } /// @@ -383,8 +223,20 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public new void Play() { - NUILog.Debug($"Play() called!"); - debugPrint(); + if (mResourceURL == null || mResourceURL == String.Empty) + { + throw new InvalidOperationException("Resource Url not yet Set"); + } + + if (mIsMinMaxSet) + { + SetPlayRange(mMinFrame, mMaxFrame); + } + else + { + SetPlayRange(0, TotalFrameNumber - 1); + } + base.Play(); AnimationState = AnimationStates.Playing; } @@ -396,8 +248,11 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public new void Pause() { - NUILog.Debug($"Pause() called!"); - debugPrint(); + if (mResourceURL == null || mResourceURL == String.Empty) + { + throw new InvalidOperationException("Resource Url not yet Set"); + } + base.Pause(); AnimationState = AnimationStates.Paused; } @@ -414,103 +269,51 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public void Stop(EndActions endAction = EndActions.Cancel) { - NUILog.Debug($"Stop()!"); + if (mResourceURL == null || mResourceURL == String.Empty) + { + throw new InvalidOperationException("Resource Url not yet Set"); + } + if (AnimationState == AnimationStates.Stopped) { return; } + if (endAction == EndActions.Discard) + { + CurrentFrame = mMinFrame; + } + else if (endAction == EndActions.StopFinal) + { + CurrentFrame = mMaxFrame; + } AnimationState = AnimationStates.Stopped; - StopEndAction = (int)endAction; - NUILog.Debug($"Stop() called!"); - debugPrint(); base.Stop(); } - #endregion + #endregion Method #region Event, Enum, Struct, ETC /// - /// Animation finished event - /// - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - public event EventHandler Finished - { - add - { - if (finishedEventHandler == null) - { - NUILog.Debug($"Finished()! add!"); - visualEventSignalCallback = onVisualEventSignal; - VisualEventSignal().Connect(visualEventSignalCallback); - } - finishedEventHandler += value; - } - remove - { - NUILog.Debug($"Finished()! remove!"); - finishedEventHandler -= value; - if (finishedEventHandler == null && visualEventSignalCallback != null) - { - VisualEventSignal().Disconnect(visualEventSignalCallback); - } - } - } - - /// - /// Enumeration for what state the vector animation is in + /// RepeatMode of animation. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - public enum PlayStateType + public enum RepeatModes { /// - /// Invalid - /// - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - Invalid = -1, - /// - /// Vector Animation has stopped - /// - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - Stopped = 0, - /// - /// The vector animation is playing + /// When the animation reaches the end and RepeatCount is nonZero, the animation restarts from the beginning. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - Playing = 1, + Restart = LoopModes.Forward, /// - /// The vector animation is paused + /// When the animation reaches the end and RepeatCount nonZero, the animation reverses direction on every animation cycle. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - Paused = 2 - } - - /// - /// AnimationStates of animation. - /// - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - public enum AnimationStates - { - /// The animation has stopped. - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - Stopped = 0, - /// The animation is playing. - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - Playing = 1, - /// The animation is paused. - // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) - [EditorBrowsable(EditorBrowsableState.Never)] - Paused = 2 + Reverse = LoopModes.Backward } /// @@ -535,288 +338,40 @@ namespace Tizen.NUI.BaseComponents } /// - /// RepeatMode of animation. + /// AnimationStates of animation. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - public enum RepeatModes + public enum AnimationStates { - /// - /// When the animation reaches the end and RepeatCount is nonZero, the animation restarts from the beginning. - /// + /// The animation has stopped. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - Restart = 1, - /// - /// When the animation reaches the end and RepeatCount nonZero, the animation reverses direction on every animation cycle. - /// + Stopped = PlayStateType.Stopped, + /// The animation is playing. + // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] + Playing = PlayStateType.Playing, + /// The animation is paused. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] - Reverse = 2 + Paused = PlayStateType.Paused } - #endregion + #endregion Event, Enum, Struct, ETC #region Internal - internal void SetPlayRange(Vector2 range) - { - PropertyMap map = new PropertyMap(); - map.Add(ImageVisualProperty.PlayRange, new PropertyValue(range)); - DoAction(vectorImageVisualIndex, (int)actionType.updateProperty, new PropertyValue(map)); - NUILog.Debug($"SetPlayRange(range min={range.X}, max={range.Y})"); - } - - internal void SetFramePlayRange(Vector2 range) - { - currentStates.framePlayRangeMin = (int)range.X; - currentStates.framePlayRangeMax = (int)range.Y; - currentStates.changed = true; - - PropertyArray array = new PropertyArray(); - array.PushBack(new PropertyValue(currentStates.framePlayRangeMin)); - array.PushBack(new PropertyValue(currentStates.framePlayRangeMax)); - - PropertyMap map = new PropertyMap(); - map.Add(ImageVisualProperty.PlayRange, new PropertyValue(array)); - DoAction(vectorImageVisualIndex, (int)actionType.updateProperty, new PropertyValue(map)); - NUILog.Debug($"SetFramePlayRange(range min={currentStates.framePlayRangeMin}, max={currentStates.framePlayRangeMax})"); - } - - internal Vector2 GetPlayRange() - { - Vector2 ret = new Vector2(-1.0f, -1.0f); - PropertyMap map = Image; - if (map != null) - { - PropertyValue val = map.Find(ImageVisualProperty.PlayRange); - if (val != null) - { - if (val.Get(ret)) - { - return ret; - } - } - } - tizenlog.Error(tag, $"[ERROR] fail to get PlayRange from dali"); - return ret; - } - - internal float CurrentProgress - { - get - { - float ret = -1.0f; - int currentFrame = -1; - PropertyMap map = Image; - if (map != null) - { - PropertyValue val = map.Find(ImageVisualProperty.CurrentFrameNumber); - if (val != null) - { - if (val.Get(out currentFrame)) - { - int total = TotalFrameNumber; - if (total != -1) - { - ret = (float)currentFrame / (float)total; - NUILog.Debug($"CurrentProgress get! currentFrame={currentFrame}, total={total}, ret={ret}"); - return ret; - } - else - { - tizenlog.Error(tag, $"[ERROR] fail to get total frame number from dali"); - return -1.0f; - } - } - } - } - tizenlog.Error(tag, $"[ERROR] fail to get CurrentProgress from dali"); - return -1.0f; - } - } - - internal int StopEndAction - { - set - { - currentStates.stopEndAction = (EndActions)value; - currentStates.changed = true; - - NUILog.Debug($"StopEndAction set val={currentStates.stopEndAction}"); - //PropertyMap map = new PropertyMap(); - //map.Add(ImageVisualProperty.StopEndAction, new PropertyValue((int)currentStates.stopEndAction)); - //DoAction(vectorImageVisualIndex, (int)actionType.updateProperty, new PropertyValue(map)); - } - get - { - NUILog.Debug($"StopEndAction get!"); - PropertyMap map = base.Image; - var ret = 0; - //if (map != null) - //{ - // PropertyValue val = map.Find(ImageVisualProperty.StopEndAction); - // if (val != null) - // { - // if (val.Get(out ret)) - // { - // NUILog.Debug($"gotten stopEndAction={ret}"); - // if (ret != (int)currentStates.stopEndAction && ret > 0) - // { - // NUILog.Debug($"different stopEndAction! gotten={ret}, stopEndAction={currentStates.stopEndAction}"); - // return (int)currentStates.stopEndAction; - // } - // return (ret); - // } - // } - //} - tizenlog.Error(tag, "[ERROR] fail to get stopEndAction from dali"); - return ret; - } - } - - internal class VisualEventSignalArgs : EventArgs - { - public int VisualIndex - { - get - { - return visualIndex; - } - set - { - visualIndex = value; - } - } - - public int SignalId - { - get - { - return signalId; - } - set - { - signalId = value; - } - } - - int visualIndex; - int signalId; - } - - internal struct states - { - internal string url; - internal int frame; - internal int loopCount; - internal RepeatModes repeatMode; - internal EndActions stopEndAction; - internal int framePlayRangeMin; - internal int framePlayRangeMax; - internal bool changed; - internal int totalFrame; - internal float scale; - }; - internal states currentStates; - - internal event EventHandler VisualEvent - { - add - { - if (visualEventSignalHandler == null) - { - visualEventSignalCallback = onVisualEventSignal; - VisualEventSignal().Connect(visualEventSignalCallback); - } - visualEventSignalHandler += value; - } - remove - { - visualEventSignalHandler -= value; - if (visualEventSignalHandler == null && VisualEventSignal().Empty() == false) - { - VisualEventSignal().Disconnect(visualEventSignalCallback); - } - } - } - - internal void EmitVisualEventSignal(int visualIndex, int signalId) - { - VisualEventSignal().Emit(this, visualIndex, signalId); - } - - internal VisualEventSignal VisualEventSignal() - { - VisualEventSignal ret = new VisualEventSignal(Interop.VisualEventSignal.NewWithView(View.getCPtr(this)), false); - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - return ret; - } - #endregion + #endregion Internal #region Private - private enum actionType - { - play, - pause, - stop, - jumpTo, - updateProperty, - }; - - private struct DevelVisual - { - internal enum Type - { - AnimatedGradient = Visual.Type.AnimatedImage + 1, - AnimatedVectorImage = Visual.Type.AnimatedImage + 2, - } - } - - private const string tag = "NUI"; - private const int vectorImageVisualIndex = 10000000 + 1000 + 2; - private event EventHandler finishedEventHandler; - - private void OnFinished() - { - finishedEventHandler?.Invoke(this, null); - } - - private void onVisualEventSignal(IntPtr targetView, int visualIndex, int signalId) - { - OnFinished(); - - if (targetView != IntPtr.Zero) - { - View v = Registry.GetManagedBaseHandleFromNativePtr(targetView) as View; - if (v != null) - { - NUILog.Debug($"targetView is not null! name={v.Name}"); - } - else - { - NUILog.Debug($"target is something created from dali"); - } - } - VisualEventSignalArgs e = new VisualEventSignalArgs(); - e.VisualIndex = visualIndex; - e.SignalId = signalId; - visualEventSignalHandler?.Invoke(this, e); - - NUILog.Debug($"@@ onVisualEventSignal()! visualIndex={visualIndex}, signalId={signalId}"); - } - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate void VisualEventSignalCallbackType(IntPtr targetView, int visualIndex, int signalId); - - private VisualEventSignalCallbackType visualEventSignalCallback; - private EventHandler visualEventSignalHandler; - - private void debugPrint() - { - NUILog.Debug($"======= currentStates"); - NUILog.Debug($"url={currentStates.url}, loopCount={currentStates.loopCount}, framePlayRangeMin={currentStates.framePlayRangeMin}, framePlayRangeMax={currentStates.framePlayRangeMax} \n"); - } - #endregion + private string mResourceURL = null; + private int mRepeatCount = 0; + private int mFrameCount = 0; + private RepeatModes mRepeatMode = RepeatModes.Restart; + private int mMinFrame = -1, mMaxFrame = -1; + private bool mIsMinMaxSet = false; + private int mCurrentFrame = -1; + #endregion Private } } -- 2.34.1