/* * Copyright(c) 2023 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 System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.ComponentModel; using Tizen.NUI; using Tizen.NUI.Binding; using Tizen.NUI.BaseComponents; namespace Tizen.NUI.Scene3D { /// /// Model is a Class to show 3D mesh objects. /// Model supports glTF 2.0 and DLI model formats. /// Physically Based Rendering with Image Based Lighting is also supported. /// /// /// /// Since NUI uses a left-handed coordinate system, loaded models are transformed into a left-handed coordinate system with Y pointing down. /// The Animations defined in the glTF or DLI are also loaded and can be retrieved by using and methods. /// The number of animation is also retrieved by GetAnimationCount() method. /// /// Model also supports Physically Based Rendering(PBR) with Image Based Lighting(IBL). /// For the IBL, two cube map textures(diffuse and specular) are required. /// Model supports 4 types layout for Cube Map: Vertical/Horizontal Cross layouts, and Vertical/Horizontal Array layouts. /// And also, ktx format with cube map is supported. /// /// The model and IBL textures start to be loaded asynchronously when the Model object is on Window. /// ResourcesLoaded signal notifies that the loading of the model and IBL resources have been completed. /// If Model or IBL is requested to be loaded before the other loading is completed, the ResourcesLoaded signal is called after all resources are loaded. /// and methods can be used after the model loading is finished. /// /// By default, the loaded mesh has its own size and inferred from position of vertices. /// The can be modified after model loading is finished. /// If user set size property, the mesh will be scaled to the input size. /// Default value of of the Model is Center. /// /// /// /// /// Model model = new Model(modelUrl) /// { /// Size = new Size(width, height), /// }; /// model.ResourcesLoaded += (s, e) => /// { /// model.PivotPoint = new Vector3(0.5f, 0.5f, 0.5f); // Use center as a Pivot. /// /// int animationCount = model.GetAnimationCount(); /// if(animationCount > 0) /// { /// // Play an Animation of index 0. /// model.GetAnimation(0).Play(); /// } /// }; /// model.SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor); /// window.Add(model); /// /// /// /// 10 public partial class Model : View { private bool isBuilt = false; private Position modelPivotPoint = new Position(); internal Model(global::System.IntPtr cPtr, bool cMemoryOwn) : this(cPtr, cMemoryOwn, cMemoryOwn) { } internal Model(global::System.IntPtr cPtr, bool cMemoryOwn, bool cRegister) : base(cPtr, cMemoryOwn, true, cRegister) { } /// /// Create an initialized Model. /// /// model file url.(e.g. glTF, and DLI). /// The url to derectory containing resources: binary, image etc. /// /// If resourceDirectoryUrl is empty, the parent directory url of modelUrl is used for resource url. /// /// http://tizen.org/privilege/mediastorage for local files in media storage. /// http://tizen.org/privilege/externalstorage for local files in external storage. /// /// 10 public Model(string modelUrl, string resourceDirectoryUrl = "") : this(Interop.Model.ModelNew(modelUrl, resourceDirectoryUrl), true) { if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); this.PositionUsesPivotPoint = true; ResourcesLoaded += OnResourcesLoaded; } /// /// Create an initialized Model. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public Model() : this(Interop.Model.ModelNew(), true) { if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); this.PositionUsesPivotPoint = true; } /// /// Copy constructor. /// /// Source object to copy. /// 10 public Model(Model model) : this(Interop.Model.NewModel(Model.getCPtr(model)), true, false) { if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); this.PositionUsesPivotPoint = model.PositionUsesPivotPoint; } /// /// Assignment operator. /// /// Source object to be assigned. /// Reference to this. internal Model Assign(Model model) { Model ret = new Model(Interop.Model.ModelAssign(SwigCPtr, Model.getCPtr(model)), false); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); ret.PositionUsesPivotPoint = model.PositionUsesPivotPoint; return ret; } /// /// Get The original pivot point of the model /// /// /// This returns (0, 0, 0) before resources are loaded. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public Position ModelPivotPoint { get { return modelPivotPoint; } } /// /// Set/Get the ImageBasedLight ScaleFactor. /// Scale factor controls light source intensity in [0.0f, 1.0f] /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public float ImageBasedLightScaleFactor { set { SetImageBasedLightScaleFactor(value); } get { return GetImageBasedLightScaleFactor(); } } /// /// Retrieves root ModelNode of this Model. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public ModelNode ModelRoot { get { return GetModelRoot(); } } /// /// Adds modelNode to this Model. /// /// Root of a ModelNode tree // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public void AddModelNode(ModelNode modelNode) { Interop.Model.AddModelNode(SwigCPtr, ModelNode.getCPtr(modelNode)); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// /// Removes modelNode from this Model. /// /// Root of a ModelNode tree to be removed // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public void RemoveModelNode(ModelNode modelNode) { Interop.Model.RemoveModelNode(SwigCPtr, ModelNode.getCPtr(modelNode)); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// /// Removes Returns a child ModelNode object with a name that matches nodeName. /// /// The name of the child ModelNode object you want to find. /// Child ModelNode that has nodeName as name. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public ModelNode FindChildModelNodeByName(string nodeName) { global::System.IntPtr cPtr = Interop.Model.FindChildModelNodeByName(SwigCPtr, nodeName); ModelNode ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ModelNode; if (ret == null) { // Store the value of PositionUsesAnchorPoint from dali object (Since View object automatically change PositionUsesPivotPoint value as false, we need to keep value.) HandleRef handle = new HandleRef(this, cPtr); // Use original value as 'true' if we got invalid ModelNode. bool originalPositionUsesAnchorPoint = (cPtr == global::System.IntPtr.Zero || !Tizen.NUI.Interop.BaseHandle.HasBody(handle)) || Object.InternalGetPropertyBool(handle, View.Property.PositionUsesAnchorPoint); handle = new HandleRef(null, IntPtr.Zero); // Register new animatable into Registry. ret = new ModelNode(cPtr, true); if (ret != null) { ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint; } } else { // We found matched NUI animatable. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.BaseHandle.DeleteBaseHandle(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Changes Image Based Light according to the given input textures. /// /// The path of Cube map image that will be used as a diffuse IBL source. /// The path of Cube map image that will be used as a specular IBL source. /// Scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f. /// /// http://tizen.org/privilege/mediastorage for local files in media storage. /// http://tizen.org/privilege/externalstorage for local files in external storage. /// /// 10 public void SetImageBasedLightSource(string diffuseUrl, string specularUrl, float scaleFactor = 1.0f) { Interop.Model.SetImageBasedLightSource(SwigCPtr, diffuseUrl, specularUrl, scaleFactor); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// /// Gets number of animations that has been loaded from model file. /// /// /// This method should be called after Model load has been finished. /// /// The number of loaded animations. /// 10 public uint GetAnimationCount() { uint ret = Interop.Model.GetAnimationCount(SwigCPtr); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Gets animation at the index. /// /// /// This method should be called after Model load has been finished. /// /// Index of animation to be retrieved. /// Animation at the index. /// 10 public Animation GetAnimation(uint index) { global::System.IntPtr cPtr = Interop.Model.GetAnimation(SwigCPtr, index); Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation; if (ret == null) { // Register new animation into Registry. ret = new Animation(cPtr, true); } else { // We found matched NUI animation. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.Animation.DeleteAnimation(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Retrieves animation with the given name. /// Note: This method should be called after Model load finished. /// /// String name of animation to be retrieved. /// Animation that has the given name. /// 10 public Animation GetAnimation(string name) { global::System.IntPtr cPtr = Interop.Model.GetAnimation(SwigCPtr, name); Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation; if (ret == null) { // Register new animation into Registry. ret = new Animation(cPtr, true); } else { // We found matched NUI animation. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.Animation.DeleteAnimation(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Gets number of camera parameters that has been loaded from model file. /// /// /// This method should be called after Model load has been finished. /// /// The number of loaded camera parameters. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public uint GetCameraCount() { uint ret = Interop.Model.GetCameraCount(SwigCPtr); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Generate Camera using camera parameters at the index. /// If camera parameter is valid, create new Camera. /// Else, return empty Handle. /// /// /// This method should be called after Model load has been finished. /// /// Index of camera to be generated. /// Generated Camera by the index, or empty Handle if generation failed. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public Camera GenerateCamera(uint index) { global::System.IntPtr cPtr = Interop.Model.GenerateCamera(SwigCPtr, index); Camera ret = new Camera(cPtr, true); // Always create new camera. if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Apply camera parameters at the index to inputed Camera. /// If camera parameter is valid and camera is not empty, apply parameters. /// It will change camera's transform and near / far / fov or orthographic size / aspect ratio (if defined) /// /// /// This method should be called after Model load has been finished. /// /// Index of camera to be retrieved. /// Camera to be applied parameter. /// True if Apply successed. False otherwise. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public bool ApplyCamera(uint index, Camera camera) { bool ret = false; if (camera?.HasBody() == true) { ret = Interop.Model.ApplyCamera(SwigCPtr, index, Camera.getCPtr(camera)); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } return ret; } /// /// Load bvh animation and assign to model. /// Scale is additional scale factor of bvh animation. It is possible that /// Model's scale may not matched with bvh animation scale. /// If scale is null, default use as Vector3.ONE /// /// Name of bvh format file. /// Scale value of bvh animation match with model. /// Whether we should translate the bvh root from it's ModelNode position or not. /// Animaion of bvh // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Do not use this LoadBvhAnimation. Use MotionData.LoadMotionCaptureAnimation and GenerateMotionDataAnimation instead.")] public Animation LoadBvhAnimation(string bvhFilename, Vector3 scale = null, bool translateRootFromModelNode = true) { global::System.IntPtr cPtr = Interop.Model.LoadBvhAnimation(SwigCPtr, bvhFilename, Vector3.getCPtr(scale), translateRootFromModelNode); Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation; if (ret == null) { // Register new animation into Registry. ret = new Animation(cPtr, true); } else { // We found matched NUI animation. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.Animation.DeleteAnimation(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Load bvh animation and assign to model. /// Scale is additional scale factor of bvh animation. It is possible that /// Model's scale may not matched with bvh animation scale. /// If scale is null, default use as Vector3.ONE /// /// Contents of bvh format file. /// Scale value of bvh animation match with model. /// Whether we should translate the bvh root from it's ModelNode position or not. /// Animaion of bvh // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Do not use this LoadBvhAnimationFromBuffer. Use MotionData.LoadMotionCaptureAnimationFromBuffer and GenerateMotionDataAnimation instead.")] public Animation LoadBvhAnimationFromBuffer(string bvhBuffer, Vector3 scale = null, bool translateRootFromModelNode = true) { global::System.IntPtr cPtr = Interop.Model.LoadBvhAnimationFromBuffer(SwigCPtr, bvhBuffer, bvhBuffer.Length, Vector3.getCPtr(scale), translateRootFromModelNode); Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation; if (ret == null) { // Register new animation into Registry. ret = new Animation(cPtr, true); } else { // We found matched NUI animation. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.Animation.DeleteAnimation(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Load facial animation and assign to model. /// /// Name of json format file what we predefined. /// Animaion of facial // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Do not use this LoadFacialAnimation. Use MotionData.LoadBlendShapeAnimation and GenerateMotionDataAnimation instead.")] public Animation LoadFacialAnimation(string facialFilename) { return LoadBlendShapeAnimation(facialFilename); } /// /// Load facial animation and assign to model. /// /// Contents of json format file what we predefined. /// Animaion of facial // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Do not use this LoadFacialAnimationFromBuffer. Use MotionData.LoadBlendShapeAnimationFromBuffer and GenerateMotionDataAnimation instead.")] public Animation LoadFacialAnimationFromBuffer(string facialBuffer) { return LoadBlendShapeAnimationFromBuffer(facialBuffer); } /// /// Load blendshape animation and assign to model from json file. /// /// Name of json format file what we predefined. /// Animaion of facial // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Do not use this LoadBlendShapeAnimation. Use MotionData.LoadBlendShapeAnimation and GenerateMotionDataAnimation instead.")] public Animation LoadBlendShapeAnimation(string jsonFilename) { global::System.IntPtr cPtr = Interop.Model.LoadBlendShapeAnimation(SwigCPtr, jsonFilename); Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation; if (ret == null) { // Register new animation into Registry. ret = new Animation(cPtr, true); } else { // We found matched NUI animation. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.Animation.DeleteAnimation(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Load morphing animation and assign to model from json string. /// /// Contents of json format file what we predefined. /// Animaion of facial // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Do not use this LoadBlendShapeAnimationFromBuffer. Use MotionData.LoadBlendShapeAnimationFromBuffer and GenerateMotionDataAnimation instead.")] public Animation LoadBlendShapeAnimationFromBuffer(string jsonBuffer) { global::System.IntPtr cPtr = Interop.Model.LoadBlendShapeAnimationFromBuffer(SwigCPtr, jsonBuffer, jsonBuffer.Length); Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation; if (ret == null) { // Register new animation into Registry. ret = new Animation(cPtr, true); } else { // We found matched NUI animation. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.Animation.DeleteAnimation(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Generate animation by MotionData. /// If there is no animatable item for MotionData, return null. /// /// Source motion data. /// Generated animation from then given motion data, or null if there is no animatable item in /// 11 public Animation GenerateMotionDataAnimation(MotionData motionData) { global::System.IntPtr cPtr = Interop.Model.GenerateMotionDataAnimation(SwigCPtr, MotionData.getCPtr(motionData)); Animation ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Animation; if (ret == null) { // Register new animation into Registry. ret = new Animation(cPtr, true); } else { // We found matched NUI animation. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.Animation.DeleteAnimation(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); // It is possible if there is no animatable properties exist on inputed motionData. // In this case, let we return null. if (!ret.HasBody()) { ret.Dispose(); ret = null; } return ret; } /// /// Set values from MotionData. /// Note that this method doesn not apply KeyFrames animation. /// If you want to apply the animation, please use and play the result. /// /// Source motion data. /// 11 public void SetMotionData(MotionData motionData) { Interop.Model.SetMotionData(SwigCPtr, MotionData.getCPtr(motionData)); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// /// Sets whether this Model casts shadow or not. /// If it is true, this model is drawn on Shadow Map. /// Note: This method affects all of the child ModelNode. /// However, same property of each child ModelNode can be changed respectively and it not changes parent's property. /// /// Whether this Model casts shadow or not. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public void CastShadow(bool castShadow) { Interop.Model.CastShadow(SwigCPtr, castShadow); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// /// Retrieves whether the Model casts shadow or not for Light. /// Note: IBL does not cast any shadow. /// /// True if this model casts shadow. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public bool IsShadowCasting() { var isShadowCasting = Interop.Model.IsShadowCasting(SwigCPtr); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return isShadowCasting; } /// /// Sets whether this Model receives shadow or not. /// If it is true, shadows are drawn on this model. /// Note: This method affects all of the child ModelNode. /// However, same property of each child ModelNode can be changed respectively and it not changes parent's property. /// /// Whether this Model receives shadow or not. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public void ReceiveShadow(bool receiveShadow) { Interop.Model.ReceiveShadow(SwigCPtr, receiveShadow); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// /// Retrieves whether the Model receives shadow or not for Light /// If it is true, this model is drawn on Shadow Map. /// /// True if this model receives shadow. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] public bool IsShadowReceiving() { var isShadowReceiving = Interop.Model.IsShadowReceiving(SwigCPtr); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return isShadowReceiving; } /// /// Retrieves model root Actor. /// /// Root View of the model. // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] private ModelNode GetModelRoot() { global::System.IntPtr cPtr = Interop.Model.GetModelRoot(SwigCPtr); ModelNode ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as ModelNode; if (ret == null) { // Store the value of PositionUsesAnchorPoint from dali object (Since View object automatically change PositionUsesPivotPoint value as false, we need to keep value.) HandleRef handle = new HandleRef(this, cPtr); // Use original value as 'true' if we got invalid ModelNode. bool originalPositionUsesAnchorPoint = (cPtr == global::System.IntPtr.Zero || !Tizen.NUI.Interop.BaseHandle.HasBody(handle)) || Object.InternalGetPropertyBool(handle, View.Property.PositionUsesAnchorPoint); handle = new HandleRef(null, IntPtr.Zero); // Register new animatable into Registry. ret = new ModelNode(cPtr, true); if (ret != null) { ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint; } } else { // We found matched NUI animatable. Reduce cPtr reference count. HandleRef handle = new HandleRef(this, cPtr); Tizen.NUI.Interop.BaseHandle.DeleteBaseHandle(handle); handle = new HandleRef(null, IntPtr.Zero); } if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Set the ImageBasedLight ScaleFactor. /// /// Scale factor that controls light source intensity in [0.0f, 1.0f]. private void SetImageBasedLightScaleFactor(float scaleFactor) { Interop.Model.SetImageBasedLightScaleFactor(SwigCPtr, scaleFactor); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// /// Get the ImageBasedLight ScaleFactor. /// /// ImageBasedLightScaleFactor that controls light source intensity. private float GetImageBasedLightScaleFactor() { float scaleFactor = Interop.Model.GetImageBasedLightScaleFactor(SwigCPtr); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return scaleFactor; } private void OnResourcesLoaded(object sender, EventArgs e) { if (!isBuilt && this.ModelRoot != null) { this.ModelRoot.Build(); isBuilt = true; this.modelPivotPoint.X = this.PivotPoint.X; this.modelPivotPoint.Y = this.PivotPoint.Y; this.modelPivotPoint.Z = this.PivotPoint.Z; } } /// /// To make transitionSet instance be disposed. /// protected override void Dispose(DisposeTypes type) { if (disposed) { return; } ResourcesLoaded -= OnResourcesLoaded; base.Dispose(type); } /// /// Release swigCPtr. /// // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API) [EditorBrowsable(EditorBrowsableState.Never)] protected override void ReleaseSwigCPtr(global::System.Runtime.InteropServices.HandleRef swigCPtr) { Interop.Model.DeleteModel(swigCPtr); } private EventHandler meshHitEventHandler; private MeshHitCallbackType meshHitCallback; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void MeshHitCallbackType(IntPtr motionData); /// /// MeshHitEventArgs /// Contains arguments when MeshHitSignal called /// [EditorBrowsable(EditorBrowsableState.Never)] public class MeshHitEventArgs : EventArgs { private ModelNode modelNode; /// /// ModelNode that's been hit /// [EditorBrowsable(EditorBrowsableState.Never)] public ModelNode ModelNode { get { return modelNode; } set { modelNode = value; } } } /// /// EventHandler event. /// It will be invoked when collider mesh is hit. /// [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler ColliderMeshHitted { add { if (meshHitEventHandler == null) { meshHitCallback = MeshHitCollision; Interop.Model.MeshHitSignalConnect(SwigCPtr, meshHitCallback.ToHandleRef(this)); NDalicPINVOKE.ThrowExceptionIfExists(); } meshHitEventHandler += value; } remove { meshHitEventHandler -= value; if (meshHitEventHandler == null && meshHitCallback != null) { Interop.Model.MeshHitSignalDisconnect(SwigCPtr, meshHitCallback.ToHandleRef(this)); NDalicPINVOKE.ThrowExceptionIfExists(); meshHitCallback = null; } } } private void MeshHitCollision(IntPtr modelNode) { if (meshHitEventHandler != null) { var args = new MeshHitEventArgs(); args.ModelNode = new ModelNode(modelNode, false); meshHitEventHandler(this, args); } } } }