[NUI.Scene3D] Fix exception when ModelNode don't have ModelNode as child
authorEunki, Hong <eunkiki.hong@samsung.com>
Tue, 14 Nov 2023 08:17:11 +0000 (17:17 +0900)
committerJaehyun Cho <jaehyun0cho@gmail.com>
Wed, 15 Nov 2023 08:56:46 +0000 (17:56 +0900)
If ModelNode don't have ModelNod as child, it might have
some null handle exception when we DownCast to ModelNode.
(For example, user try to get child ModelNode, but failed.)

Currently, a lots of app don't consider ModelNode now. But in future
we might need to add something under each ModelNode.

To make Scene3D more safety, let we check null or invalidate,
and then get/set the value internally.

Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
src/Tizen.NUI.Scene3D/src/public/Controls/Model.cs
src/Tizen.NUI.Scene3D/src/public/ModelComponents/ModelNode.cs

index 125e0d336acd6b65cb1d9a13bf1cb9f6a412f0cb..2b156381e0078a0b1e22908e7b9cc969589c4492 100755 (executable)
@@ -209,12 +209,17 @@ namespace Tizen.NUI.Scene3D
             {
                 // 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);
-                bool originalPositionUsesAnchorPoint = Object.InternalGetPropertyBool(handle, View.Property.PositionUsesAnchorPoint);
+
+                // 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);
-                ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
+                if (ret != null)
+                {
+                    ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
+                }
             }
             else
             {
@@ -585,12 +590,17 @@ namespace Tizen.NUI.Scene3D
             {
                 // 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);
-                bool originalPositionUsesAnchorPoint = Object.InternalGetPropertyBool(handle, View.Property.PositionUsesAnchorPoint);
+
+                // 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);
-                ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
+                if (ret != null)
+                {
+                    ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
+                }
             }
             else
             {
@@ -626,7 +636,7 @@ namespace Tizen.NUI.Scene3D
 
         private void OnResourcesLoaded(object sender, EventArgs e)
         {
-            if(!isBuilt && this.ModelRoot != null)
+            if (!isBuilt && this.ModelRoot != null)
             {
                 this.ModelRoot.Build();
                 isBuilt = true;
index c0dc91b72dc954e6423a9038c56e1dad6463206c..64f15bbeb937ddd7c2b006940d220b59ed145a0f 100755 (executable)
@@ -180,12 +180,17 @@ namespace Tizen.NUI.Scene3D
             {
                 // 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);
-                bool originalPositionUsesAnchorPoint = Object.InternalGetPropertyBool(handle, View.Property.PositionUsesAnchorPoint);
+
+                // 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);
-                ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
+                if (ret != null)
+                {
+                    ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
+                }
             }
             else
             {
@@ -219,14 +224,17 @@ namespace Tizen.NUI.Scene3D
         {
             List<ModelNode> childModelNodes = new List<ModelNode>();
             uint childModelNodeCount = GetChildModelNodeCount();
-            for(uint i = 0; i < childModelNodeCount; ++i)
+            for (uint i = 0; i < childModelNodeCount; ++i)
             {
                 ModelNode modelNode = GetChildModelNodeAt(i);
-                childModelNodes.Add(modelNode);
-                modelNode.Build();
+                if (modelNode != null)
+                {
+                    childModelNodes.Add(modelNode);
+                    modelNode.Build();
+                }
             }
 
-            foreach(ModelNode node in childModelNodes)
+            foreach (ModelNode node in childModelNodes)
             {
                 this.Add(node);
             }
@@ -260,12 +268,17 @@ namespace Tizen.NUI.Scene3D
             {
                 // 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);
-                bool originalPositionUsesAnchorPoint = Object.InternalGetPropertyBool(handle, View.Property.PositionUsesAnchorPoint);
+
+                // 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);
-                ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
+                if (ret != null)
+                {
+                    ret.PositionUsesPivotPoint = originalPositionUsesAnchorPoint;
+                }
             }
             else
             {