2 * Copyright(c) 2023 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 System.Runtime.InteropServices;
20 using System.ComponentModel;
21 using System.Collections.Generic;
23 namespace Tizen.NUI.Scene3D
26 /// List of model motion definitions.
27 /// Each motion has pair of <see cref="MotionIndex"/> and <see cref="MotionValue"/>.
28 /// MotionIndex is abstract class that specify the target of motion.
29 /// MotionValue is destination value of target for the motion. It can be expressed with <see cref="Tizen.NUI.PropertyValue"/> or <see cref="Tizen.NUI.KeyFrames"/>.
32 /// We don't check duplicated MotionIndex internally.
33 /// We don't check MotionValue type is matched with MotionIndex.
36 /// We can generate list of motions by MotionIndex and MotionValue classes.
39 /// MotionData motionData = new MotionData(3.0f);
41 /// // Make MotionIndex with MotionPropertyIndex
42 /// // Make MotionValue with PropertyValue
43 /// motionData.Add(new MotionPropertyIndex(new PropertyKey("nodeName"), new PropertyKey("color")), new MotionValue(new PropertyValue(Color.Red)));
45 /// // Make MotionIndex with MotionTransformIndex
46 /// // Make MotionValue with Dali::KeyFrames
47 /// KeyFrames keyFrames = new KeyFrames();
48 /// keyFrames.Add(0.0f, 0.0f);
49 /// keyFrames.Add(0.0f, 1.0f);
50 /// motionData.Add(new MotionTransformIndex(new PropertyKey("nodeName"), MotionTransformIndex.TransformType.PositionX), new MotionValue(keyFrames));
52 /// // Make MotionIndex with BlendShapeIndex
53 /// motionData.Add(new BlendShapeIndex(new PropertyKey("nodeName"), new PropertyKey("blendShapeName")), motionData.GetValue(1u));
57 /// We can request to load MotionData from file or buffer asynchronously.
58 /// If load completed, <see cref="LoadCompleted"/> event will be invoked.
59 /// If we try to load before LoadCompleted event invoked, previous load request cancel and only latest request loaded.
62 /// MotionData motionData = new MotionData();
63 /// motionData.LoadCompleted += OnLoadCompleted;
64 /// motionData.LoadBvh("bvhFilename.bvh", Vector3.One);
68 /// void OnLoadCompleted(object o, event e)
70 /// MotionData motionData = o as MotionData;
76 /// We can generate animation of Scene3D.Model from MotionData class.
77 /// Or, just set values.
80 /// // Generate animation from loaded Model
81 /// Animation animation = model.GenerateMotionDataAnimation(motionData);
84 /// // Set values from loaded Model.
85 /// model2.SetMotionData(motionData);
88 [EditorBrowsable(EditorBrowsableState.Never)]
89 public class MotionData : BaseHandle
91 private EventHandler loadCompletedEventHandler;
92 private LoadCompletedCallbackType loadCompletedCallback;
93 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
94 private delegate void LoadCompletedCallbackType(IntPtr motionData);
97 /// Create an initialized, empty motion data.
99 [EditorBrowsable(EditorBrowsableState.Never)]
100 public MotionData() : this(Interop.MotionData.MotionDataNew(), true)
102 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
106 /// Create an initialized motion data with duration.
108 /// <param name="durationMilliseconds">Duration of an Animation generated from this motion data, in milliseconds.</param>
109 [EditorBrowsable(EditorBrowsableState.Never)]
110 public MotionData(int durationMilliseconds) : this(Interop.MotionData.MotionDataNew(MillisecondsToSeconds(durationMilliseconds)), true)
112 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
116 /// Copy constructor.
118 /// <param name="motionData">Source object to copy.</param>
119 [EditorBrowsable(EditorBrowsableState.Never)]
120 public MotionData(MotionData motionData) : this(Interop.MotionData.NewMotionData(MotionData.getCPtr(motionData)), true)
122 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
126 /// Assignment operator.
128 /// <param name="motionData">Source object to be assigned.</param>
129 /// <returns>Reference to this.</returns>
130 internal MotionData Assign(MotionData motionData)
132 MotionData ret = new MotionData(Interop.MotionData.MotionDataAssign(SwigCPtr, MotionData.getCPtr(motionData)), false);
133 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
137 internal MotionData(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
142 /// Get or set the duration of this motion data in milliseconds.
144 [EditorBrowsable(EditorBrowsableState.Never)]
149 return SecondsToMilliseconds(GetDuration());
153 SetDuration(MillisecondsToSeconds(value));
158 /// Get the number of contained MotionIndex / MotionValue pair what this hold.
160 /// <returns>The number of contained motions.</returns>
161 [EditorBrowsable(EditorBrowsableState.Never)]
162 public uint GetMotionCount()
164 uint ret = Interop.MotionData.GetMotionCount(SwigCPtr);
165 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
170 /// Append pair of MotionIndex and MotionValue to the list.
172 /// <param name="index">MotionIndex to be added</param>
173 /// <param name="value">MotionValue to be added</param>
174 [EditorBrowsable(EditorBrowsableState.Never)]
175 public void Add(MotionIndex index, MotionValue value)
177 Interop.MotionData.Add(SwigCPtr, MotionIndex.getCPtr(index), MotionValue.getCPtr(value));
178 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
182 /// Get MotionIndex at position, or null if invalid index was given.
184 /// <param name="index">The index of motion data list</param>
185 /// <returns>The MotionIndex at position. Or null.</returns>
186 [EditorBrowsable(EditorBrowsableState.Never)]
187 public MotionIndex GetIndex(uint index)
189 IntPtr cPtr = Interop.MotionData.GetIndex(SwigCPtr, index);
190 MotionIndex ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as MotionIndex;
193 // Register new animation into Registry.
194 ret = new MotionIndex(cPtr, true);
198 // We found matched NUI animation. Reduce cPtr reference count.
199 HandleRef handle = new HandleRef(this, cPtr);
200 Interop.MotionIndex.DeleteMotionIndex(handle);
201 handle = new HandleRef(null, IntPtr.Zero);
203 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
214 /// Get MotionValue at position, or null if invalid index was given.
216 /// <param name="index">The index of motion data list</param>
217 /// <returns>The MotionValue at position. Or null.</returns>
218 [EditorBrowsable(EditorBrowsableState.Never)]
219 public MotionValue GetValue(uint index)
221 IntPtr cPtr = Interop.MotionData.GetValue(SwigCPtr, index);
222 MotionValue ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as MotionValue;
225 // Register new animation into Registry.
226 ret = new MotionValue(cPtr, true);
230 // We found matched NUI animation. Reduce cPtr reference count.
231 HandleRef handle = new HandleRef(this, cPtr);
232 Interop.MotionValue.DeleteMotionValue(handle);
233 handle = new HandleRef(null, IntPtr.Zero);
235 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
246 /// Load motion capture animation.
247 /// We support bvh format.
248 /// After load completes, <see cref="LoadCompleted"/> event will be invoked.
251 /// Scale is additional scale factor of motion capture animation. It is possible that
252 /// Model's scale may not match with motion capture animation scale.
253 /// If scale is null, default value will be used: <cref name="Vector3.ONE"/>
255 /// <param name="motionCaptureFilename">Name of motion capture format file.</param>
256 /// <param name="scale">Scale value of motion capture animation match with model.</param>
257 /// <param name="synchronousLoad">Load synchronously or not. Default is async load.</param>
258 [EditorBrowsable(EditorBrowsableState.Never)]
259 public void LoadMotionCaptureAnimation(string motionCaptureFilename, Vector3 scale = null, bool synchronousLoad = false)
261 Interop.MotionData.LoadMotionCaptureAnimation(SwigCPtr, motionCaptureFilename, Vector3.getCPtr(scale), synchronousLoad);
262 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
266 /// Load motion capture animation from string.
267 /// We support bvh format.
268 /// After load completes, <see cref="LoadCompleted"/> event will be invoked.
271 /// Scale is additional scale factor of motion capture animation. It is possible that
272 /// Model's scale may not match with motion capture animation scale.
273 /// If scale is null, default value will be used: <cref name="Vector3.ONE"/>
275 /// <param name="motionCaptureBuffer">Contents of motion capture format string.</param>
276 /// <param name="scale">Scale value of motion capture animation match with model.</param>
277 /// <param name="synchronousLoad">Load synchronously or not. Default is async load.</param>
278 [EditorBrowsable(EditorBrowsableState.Never)]
279 public void LoadMotionCaptureAnimationFromBuffer(string motionCaptureBuffer, Vector3 scale = null, bool synchronousLoad = false)
281 Interop.MotionData.LoadMotionCaptureAnimationFromBuffer(SwigCPtr, motionCaptureBuffer, motionCaptureBuffer.Length, Vector3.getCPtr(scale), synchronousLoad);
282 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
286 /// Load blendshape animation from json file.
287 /// After load completed, <see cref="LoadCompleted"/> event will be invoked.
289 /// <param name="blendShapeFilename">Name of json format file what we predefined.</param>
290 /// <param name="synchronousLoad">Load synchronously or not. Default is async load.</param>
291 [EditorBrowsable(EditorBrowsableState.Never)]
292 public void LoadBlendShapeAnimation(string blendShapeFilename, bool synchronousLoad = false)
294 Interop.MotionData.LoadBlendShapeAnimation(SwigCPtr, blendShapeFilename, synchronousLoad);
295 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
299 /// Load morphing animation from json string.
300 /// After load completed, <see cref="LoadCompleted"/> event will be invoked.
302 /// <param name="blendShapeBuffer">Contents of json format file what we predefined.</param>
303 /// <param name="synchronousLoad">Load synchronously or not. Default is async load.</param>
304 [EditorBrowsable(EditorBrowsableState.Never)]
305 public void LoadBlendShapeAnimationFromBuffer(string blendShapeBuffer, bool synchronousLoad = false)
307 Interop.MotionData.LoadBlendShapeAnimationFromBuffer(SwigCPtr, blendShapeBuffer, blendShapeBuffer.Length, synchronousLoad);
308 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
312 /// LoadCompleted event.
313 /// It will be invoked only for latest load request.
315 [EditorBrowsable(EditorBrowsableState.Never)]
316 public event EventHandler LoadCompleted
320 if (loadCompletedEventHandler == null)
322 loadCompletedCallback = OnLoadCompleted;
323 Interop.MotionData.LoadCompletedConnect(SwigCPtr, loadCompletedCallback.ToHandleRef(this));
324 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
327 loadCompletedEventHandler += value;
331 loadCompletedEventHandler -= value;
332 if (loadCompletedEventHandler == null && loadCompletedCallback != null)
334 Interop.MotionData.LoadCompletedDisconnect(SwigCPtr, loadCompletedCallback.ToHandleRef(this));
335 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
336 loadCompletedCallback = null;
341 private void OnLoadCompleted(IntPtr motionData)
343 if (loadCompletedEventHandler != null)
345 loadCompletedEventHandler(this, null);
350 /// Removes all stored motions.
352 [EditorBrowsable(EditorBrowsableState.Never)]
355 Interop.MotionData.Clear(SwigCPtr);
356 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
359 internal void SetDuration(float durationSeconds)
361 Interop.MotionData.SetDuration(SwigCPtr, durationSeconds);
362 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
365 internal float GetDuration()
367 float ret = Interop.MotionData.GetDuration(SwigCPtr);
368 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
372 private static float MillisecondsToSeconds(int millisec)
374 return (float)millisec / 1000.0f;
377 private static int SecondsToMilliseconds(float sec)
379 return (int)(sec * 1000);
383 /// you can override it to clean-up your own resources.
385 /// <param name="type">DisposeTypes</param>
386 // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
387 [EditorBrowsable(EditorBrowsableState.Never)]
388 protected override void Dispose(DisposeTypes type)
395 if (type == DisposeTypes.Explicit)
398 //Release your own managed resources here.
399 //You should release all of your own disposable objects here.
402 //Release your own unmanaged resources here.
403 //You should not access any managed member here except static instance.
404 //because the execution order of Finalizes is non-deterministic.
406 if (loadCompletedCallback != null)
408 NUILog.Debug($"[Dispose] loadCompletedCallback");
410 Interop.MotionData.LoadCompletedDisconnect(SwigCPtr, loadCompletedCallback.ToHandleRef(this));
411 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
412 loadCompletedCallback = null;
419 /// Release swigCPtr.
421 // This will be public opened.
422 [EditorBrowsable(EditorBrowsableState.Never)]
423 protected override void ReleaseSwigCPtr(global::System.Runtime.InteropServices.HandleRef swigCPtr)
425 Interop.MotionData.DeleteMotionData(swigCPtr);