[dali_2.2.16] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-scene3d-internal / utc-Dali-DliLoaderImpl.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // Enable debug log for test coverage
19 #define DEBUG_ENABLED 1
20
21 #include <dali-scene3d/internal/loader/dli-loader-impl.h>
22 #include <dali-scene3d/internal/loader/json-util.h>
23 #include <dali-scene3d/public-api/loader/load-result.h>
24 #include <dali-scene3d/public-api/loader/resource-bundle.h>
25 #include <dali-scene3d/public-api/loader/scene-definition.h>
26 #include <dali-test-suite-utils.h>
27 #include <string_view>
28
29 using namespace Dali;
30 using namespace Dali::Scene3D::Loader;
31
32 namespace
33 {
34 void ConfigureBlendShapeShaders(ResourceBundle& resources, const SceneDefinition& scene, Actor root, std::vector<BlendshapeShaderConfigurationRequest>&& requests)
35 {
36   std::vector<std::string> errors;
37   auto                     onError = [&errors](const std::string& msg)
38   {
39     errors.push_back(msg);
40   };
41
42   if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError))
43   {
44     ExceptionFlinger flinger(ASSERT_LOCATION);
45     for(auto& msg : errors)
46     {
47       flinger << msg << '\n';
48     }
49   }
50 }
51
52 struct Context
53 {
54   ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type)
55   {
56     return TEST_RESOURCE_DIR "/";
57   };
58
59   ResourceBundle                        resources;
60   SceneDefinition                       scene;
61   std::vector<CameraParameters>         cameraParameters;
62   std::vector<LightParameters>          lights;
63   std::vector<AnimationDefinition>      animations;
64   std::vector<AnimationGroupDefinition> animGroups;
65
66   SceneMetadata metaData;
67
68   LoadResult output{
69     resources,
70     scene,
71     metaData,
72     animations,
73     animGroups,
74     cameraParameters,
75     lights};
76
77   Dali::Scene3D::Loader::DliInputParameter       input;
78   std::vector<std::string>                       errors;
79   Dali::Scene3D::Loader::Internal::DliLoaderImpl loader;
80
81   StringCallback onError = [this](const std::string& error)
82   {
83     errors.push_back(error);
84     printf("%s\n", error.c_str());
85   };
86
87   Context()
88   {
89     input.mAnimationsPath = pathProvider(ResourceType::Mesh);
90     loader.SetErrorCallback(onError);
91     loader.SetInputParameter(input);
92   }
93 };
94
95 bool StringHasTokens(const char* string, const std::vector<const char*>& tokens)
96 {
97   for(auto& token : tokens)
98   {
99     auto result = strstr(string, token);
100     if(nullptr == result)
101     {
102       return false;
103     }
104     string = result + strlen(token);
105   }
106   return true;
107 }
108
109 } // namespace
110
111 int UtcDaliDliLoaderLoadSceneNotFound(void)
112 {
113   Context ctx;
114
115   DALI_TEST_EQUAL(ctx.loader.LoadModel("does_not_exist.dli", ctx.output), false);
116
117   auto error = ctx.loader.GetParseError();
118   DALI_TEST_CHECK(StringHasTokens(error.c_str(), {"Empty source buffer to parse."}));
119
120   END_TEST;
121 }
122
123 int UtcDaliDliLoaderLoadSceneFailParse(void)
124 {
125   Context ctx;
126
127   auto path = ctx.pathProvider(ResourceType::Mesh) + "invalid.gltf";
128   DALI_TEST_EQUAL(ctx.loader.LoadModel(path, ctx.output), false);
129
130   auto error = ctx.loader.GetParseError();
131   DALI_TEST_CHECK(StringHasTokens(error.c_str(), {"Unexpected character."}));
132
133   END_TEST;
134 }
135
136 int UtcDaliDliLoaderLoadSceneAssertions(void)
137 {
138   const std::pair<std::string, std::string> pathExceptionPairs[]{
139     // from RequireChild()
140     {"scenes-nodes-missing", "Failed to find child node"},
141     {"scenes-missing", "Failed to find child node"},
142     {"nodes-missing", "Failed to find child node"},
143     // from ParseSceneInternal()
144     {"scene-out-of-bounds", "out of bounds"},
145     {"nodes-invalid-type", "invalid type; array required"},
146     {"nodes-array-empty", "must define a node id"},
147     {"root-id-invalid", "invalid value for root node index"},
148     {"root-id-out-of-bounds", "out of bounds"},
149     {"root-node-invalid-type", "invalid JSON type; object required"},
150     // from ParseSkeletons()
151     {"skeleton-node-missing", "Missing required attribute"},
152     {"skeleton-root-not-found", "not defined"},
153     // from ParseShaders()
154     {"shader-vertex-missing", "Missing vertex / fragment shader"},
155     {"shader-fragment-missing", "Missing vertex / fragment shader"},
156     // from ParseMeshes()
157     {"mesh-uri-missing", "Missing required attribute"},
158     {"mesh-indices-read-fail", "Failed to read indices"},
159     {"mesh-positions-read-fail", "Failed to read positions"},
160     // from ParseMaterials()
161     {"material-environment-out-of-bounds", "out of bounds"},
162     // from ParseNodes()
163     {"node-model-mesh-missing", "Missing mesh"},
164     {"node-arc-mesh-missing", "Missing mesh"},
165     {"node-animated-image-mesh-missing", "Missing mesh"},
166     {"node-renderable-mesh-invalid-type", "Invalid Mesh index type"},
167     {"node-renderable-mesh-out-of-bounds", "out of bounds"},
168     {"node-child-invalid-type", "invalid index type"},
169     // from ParseAnimations()
170     {"animation-failed-to-open", "Failed to open animation data"}};
171   for(auto& i : pathExceptionPairs)
172   {
173     Context ctx;
174
175     auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/" + i.first + ".dli";
176     printf("\n\n%s: %s\n", path.c_str(), i.second.c_str());
177     DALI_TEST_ASSERTION(ctx.loader.LoadModel(path, ctx.output), i.second.c_str());
178   }
179
180   END_TEST;
181 }
182
183 int UtcDaliDliLoaderLoadSceneExercise(void)
184 {
185   Context ctx;
186
187   auto path = ctx.pathProvider(ResourceType::Mesh) + "exercise.dli";
188   DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output));
189   DALI_TEST_CHECK(ctx.errors.empty());
190
191   auto& scene = ctx.scene;
192   auto& roots = scene.GetRoots();
193   DALI_TEST_EQUAL(roots.size(), 2u);
194   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "Backdrop"); // default scene is scene 1 - this one.
195   DALI_TEST_EQUAL(scene.GetNode(roots[1])->mName, "ExerciseDemo");
196
197   DALI_TEST_EQUAL(scene.GetNodeCount(), 96u);
198
199   auto& resources = ctx.resources;
200   DALI_TEST_EQUAL(resources.mMeshes.size(), 11u);
201   DALI_TEST_EQUAL(resources.mMaterials.size(), 13u);
202   DALI_TEST_EQUAL(resources.mShaders.size(), 5u);
203   DALI_TEST_EQUAL(resources.mEnvironmentMaps.size(), 2u);
204   DALI_TEST_EQUAL(resources.mSkeletons.size(), 1u);
205
206   DALI_TEST_EQUAL(ctx.cameraParameters.size(), 1u);
207   DALI_TEST_EQUAL(ctx.lights.size(), 1u);
208   DALI_TEST_EQUAL(ctx.animations.size(), 18u);
209   DALI_TEST_EQUAL(ctx.animGroups.size(), 16u);
210
211   ViewProjection viewProjection;
212   Transforms     xforms{
213     MatrixStack{},
214     viewProjection};
215   NodeDefinition::CreateParams nodeParams{
216     resources,
217     xforms,
218   };
219
220   Customization::Choices choices;
221
222   TestApplication app;
223
224   Actor root = Actor::New();
225   SetActorCentered(root);
226   for(auto iRoot : scene.GetRoots())
227   {
228     auto resourceRefs = resources.CreateRefCounter();
229     scene.CountResourceRefs(iRoot, choices, resourceRefs);
230     resources.mReferenceCounts = std::move(resourceRefs);
231     resources.CountEnvironmentReferences();
232     resources.LoadResources(ctx.pathProvider);
233     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
234     {
235       scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
236       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
237       ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
238       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
239       root.Add(actor);
240     }
241   }
242
243   DALI_TEST_EQUAL(root.GetChildCount(), 2u);
244   DALI_TEST_EQUAL(root.GetChildAt(0).GetProperty(Actor::Property::NAME).Get<std::string>(), "Backdrop");
245   DALI_TEST_EQUAL(root.GetChildAt(1).GetProperty(Actor::Property::NAME).Get<std::string>(), "ExerciseDemo");
246
247   END_TEST;
248 }
249
250 int UtcDaliDliLoaderLoadSceneMorph(void)
251 {
252   Context ctx;
253
254   std::vector<std::string> metadata;
255   uint32_t                 metadataCount = 0;
256   ctx.input.mPreNodeCategoryProcessors.push_back({"metadata",
257                                                   [&](const Property::Array& array, StringCallback)
258                                                   {
259                                                     std::string key, value;
260                                                     for(uint32_t i0 = 0, i1 = array.Count(); i0 < i1; ++i0)
261                                                     {
262                                                       auto& data = array.GetElementAt(i0);
263                                                       DALI_TEST_EQUAL(data.GetType(), Property::MAP);
264
265                                                       auto map   = data.GetMap();
266                                                       auto key   = map->Find("key");
267                                                       auto value = map->Find("value");
268                                                       DALI_TEST_EQUAL(key->GetType(), Property::STRING);
269                                                       DALI_TEST_EQUAL(value->GetType(), Property::STRING);
270                                                       metadata.push_back(key->Get<std::string>() + ":" + value->Get<std::string>());
271
272                                                       ++metadataCount;
273                                                     }
274                                                   }});
275
276   std::vector<std::string> behaviors;
277   uint32_t                 behaviorCount = 0;
278   ctx.input.mPostNodeCategoryProcessors.push_back({"behaviors",
279                                                    [&](const Property::Array& array, StringCallback)
280                                                    {
281                                                      for(uint32_t i0 = 0, i1 = array.Count(); i0 < i1; ++i0)
282                                                      {
283                                                        auto& data = array.GetElementAt(i0);
284                                                        DALI_TEST_EQUAL(data.GetType(), Property::MAP);
285
286                                                        auto map   = data.GetMap();
287                                                        auto event = map->Find("event");
288                                                        auto url   = map->Find("url");
289                                                        DALI_TEST_EQUAL(event->GetType(), Property::STRING);
290                                                        DALI_TEST_EQUAL(url->GetType(), Property::STRING);
291                                                        behaviors.push_back(event->Get<std::string>() + ":" + url->Get<std::string>());
292
293                                                        ++behaviorCount;
294                                                      }
295                                                    }});
296
297   size_t numNodes                  = 0;
298   ctx.input.mNodePropertyProcessor = [&](const NodeDefinition&, const Property::Map&, StringCallback)
299   {
300     ++numNodes;
301   };
302
303   auto path = ctx.pathProvider(ResourceType::Mesh) + "morph.dli";
304   DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output));
305   DALI_TEST_CHECK(ctx.errors.empty());
306
307   auto& scene = ctx.scene;
308   auto& roots = scene.GetRoots();
309   DALI_TEST_EQUAL(roots.size(), 1u);
310   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "HeadTest_002");
311
312   DALI_TEST_EQUAL(numNodes, 3u);
313   DALI_TEST_EQUAL(scene.GetNodeCount(), numNodes);
314
315   auto& resources = ctx.resources;
316   DALI_TEST_EQUAL(resources.mMeshes.size(), 2u);
317   DALI_TEST_EQUAL(resources.mMaterials.size(), 1u);
318   DALI_TEST_EQUAL(resources.mShaders.size(), 5u);
319   DALI_TEST_EQUAL(resources.mEnvironmentMaps.size(), 2u);
320   DALI_TEST_EQUAL(resources.mSkeletons.size(), 0u);
321
322   DALI_TEST_EQUAL(ctx.cameraParameters.size(), 1u);
323   DALI_TEST_EQUAL(ctx.lights.size(), 1u);
324   DALI_TEST_EQUAL(ctx.animations.size(), 1u);
325   DALI_TEST_EQUAL(ctx.animGroups.size(), 0u);
326
327   DALI_TEST_EQUAL(metadata.size(), 4u);
328   DALI_TEST_EQUAL(behaviors.size(), 1u);
329
330   ViewProjection viewProjection;
331   Transforms     xforms{
332     MatrixStack{},
333     viewProjection};
334   NodeDefinition::CreateParams nodeParams{
335     resources,
336     xforms,
337   };
338
339   Customization::Choices choices;
340
341   TestApplication app;
342
343   Actor root = Actor::New();
344   SetActorCentered(root);
345   for(auto iRoot : scene.GetRoots())
346   {
347     auto resourceRefs = resources.CreateRefCounter();
348     scene.CountResourceRefs(iRoot, choices, resourceRefs);
349     resources.mReferenceCounts = std::move(resourceRefs);
350     resources.CountEnvironmentReferences();
351     resources.LoadResources(ctx.pathProvider);
352     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
353     {
354       scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
355       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
356       ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
357       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
358       root.Add(actor);
359     }
360   }
361
362   DALI_TEST_EQUAL(root.GetChildCount(), 1u);
363   DALI_TEST_EQUAL(root.GetChildAt(0).GetProperty(Actor::Property::NAME).Get<std::string>(), "HeadTest_002");
364
365   END_TEST;
366 }
367
368 int UtcDaliDliLoaderLoadSceneArc(void)
369 {
370   Context ctx;
371
372   auto path = ctx.pathProvider(ResourceType::Mesh) + "arc.dli";
373   DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output));
374   DALI_TEST_CHECK(ctx.errors.empty());
375
376   auto& scene = ctx.scene;
377   auto& roots = scene.GetRoots();
378   DALI_TEST_EQUAL(roots.size(), 1u);
379   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "root");
380
381   DALI_TEST_EQUAL(scene.GetNodeCount(), 2u);
382
383   auto& resources = ctx.resources;
384   DALI_TEST_EQUAL(resources.mMeshes.size(), 1u);
385   DALI_TEST_EQUAL(resources.mMaterials.size(), 1u);
386   DALI_TEST_EQUAL(resources.mShaders.size(), 1u);
387   DALI_TEST_EQUAL(resources.mEnvironmentMaps.size(), 1u);
388   DALI_TEST_EQUAL(resources.mSkeletons.size(), 0u);
389
390   DALI_TEST_EQUAL(ctx.cameraParameters.size(), 0u);
391   DALI_TEST_EQUAL(ctx.lights.size(), 0u);
392   DALI_TEST_EQUAL(ctx.animations.size(), 0u);
393   DALI_TEST_EQUAL(ctx.animGroups.size(), 0u);
394
395   ViewProjection viewProjection;
396   Transforms     xforms{
397     MatrixStack{},
398     viewProjection};
399   NodeDefinition::CreateParams nodeParams{
400     resources,
401     xforms,
402   };
403
404   Customization::Choices choices;
405
406   TestApplication app;
407
408   Actor root = Actor::New();
409   SetActorCentered(root);
410   for(auto iRoot : scene.GetRoots())
411   {
412     auto resourceRefs = resources.CreateRefCounter();
413     scene.CountResourceRefs(iRoot, choices, resourceRefs);
414     resources.mReferenceCounts = std::move(resourceRefs);
415     resources.CountEnvironmentReferences();
416     resources.LoadResources(ctx.pathProvider);
417     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
418     {
419       scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
420       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
421       ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
422       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
423       root.Add(actor);
424     }
425   }
426
427   DALI_TEST_EQUAL(root.GetChildCount(), 1u);
428   DALI_TEST_EQUAL(root.GetChildAt(0).GetProperty(Actor::Property::NAME).Get<std::string>(), "root");
429
430   END_TEST;
431 }
432
433 int UtcDaliDliLoaderLoadSceneShaderUniforms(void)
434 {
435   Context ctx;
436
437   auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/shader-uniforms.dli";
438   DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output));
439   DALI_TEST_EQUAL(ctx.errors.size(), 1u);
440   DALI_TEST_CHECK(ctx.errors[0].find("failed to infer type") != std::string::npos);
441
442   auto& scene = ctx.scene;
443   auto& roots = scene.GetRoots();
444   DALI_TEST_EQUAL(roots.size(), 1u);
445   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "root");
446
447   DALI_TEST_EQUAL(scene.GetNodeCount(), 1u);
448
449   auto& resources = ctx.resources;
450   DALI_TEST_EQUAL(resources.mMeshes.size(), 0u);
451   DALI_TEST_EQUAL(resources.mMaterials.size(), 0u);
452   DALI_TEST_EQUAL(resources.mShaders.size(), 1u);
453   DALI_TEST_EQUAL(resources.mEnvironmentMaps.size(), 0u);
454   DALI_TEST_EQUAL(resources.mSkeletons.size(), 0u);
455
456   auto raw = resources.mShaders[0].first.LoadRaw(ctx.pathProvider(ResourceType::Shader));
457
458   TestApplication app;
459
460   auto shader = resources.mShaders[0].first.Load(std::move(raw));
461   DALI_TEST_EQUAL(shader.GetProperty(shader.GetPropertyIndex("uBool")).Get<float>(), 1.0f);
462   DALI_TEST_EQUAL(shader.GetProperty(shader.GetPropertyIndex("uInt")).Get<float>(), 255.0f);
463   DALI_TEST_EQUAL(shader.GetProperty(shader.GetPropertyIndex("uFloat")).Get<float>(), -0.5f);
464   DALI_TEST_EQUAL(shader.GetProperty(shader.GetPropertyIndex("uVec2")).Get<Vector2>(), Vector2(100.0f, -100.0f));
465   DALI_TEST_EQUAL(shader.GetProperty(shader.GetPropertyIndex("uVec3")).Get<Vector3>(), Vector3(50.0f, 0.f, -200.0f));
466   DALI_TEST_EQUAL(shader.GetProperty(shader.GetPropertyIndex("uVec4")).Get<Vector4>(), Vector4(0.1774f, 1.0f, 0.5333f, 0.7997f));
467   DALI_TEST_EQUAL(shader.GetProperty(shader.GetPropertyIndex("uMat3")).Get<Matrix3>(), Matrix3(9.0f, 8.0f, 7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f));
468
469   Matrix expectedMatrix;
470   expectedMatrix.SetTransformComponents(Vector3::ONE * 8.0, Quaternion::IDENTITY, Vector3::ZERO);
471   DALI_TEST_EQUAL(shader.GetProperty(shader.GetPropertyIndex("uMat4")).Get<Matrix>(), expectedMatrix);
472
473   END_TEST;
474 }
475
476 int UtcDaliDliLoaderLoadSceneExtras(void)
477 {
478   Context ctx;
479
480   auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/extras.dli";
481   DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output));
482   DALI_TEST_EQUAL(ctx.errors.size(), 3u);
483   DALI_TEST_CHECK(ctx.errors[0].find("already defined; overriding") != std::string::npos);
484   DALI_TEST_CHECK(ctx.errors[1].find("empty string is invalid for name") != std::string::npos);
485   DALI_TEST_CHECK(ctx.errors[2].find("failed to interpret value") != std::string::npos);
486
487   auto& scene = ctx.scene;
488   auto& roots = scene.GetRoots();
489   DALI_TEST_EQUAL(roots.size(), 1u);
490   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "root");
491
492   DALI_TEST_EQUAL(scene.GetNodeCount(), 1u);
493
494   ViewProjection viewProjection;
495   Transforms     xforms{
496     MatrixStack{},
497     viewProjection};
498   auto&                        resources = ctx.resources;
499   NodeDefinition::CreateParams nodeParams{
500     resources,
501     xforms,
502   };
503
504   Customization::Choices choices;
505
506   TestApplication app;
507   Actor           actor = scene.CreateNodes(0, choices, nodeParams);
508
509   DALI_TEST_EQUAL(actor.GetProperty(actor.GetPropertyIndex("fudgeFactor")).Get<float>(), 9000.1f);
510   DALI_TEST_EQUAL(actor.GetProperty(actor.GetPropertyIndex("fudgeVector")).Get<Vector2>(), Vector2(-.25f, 17.f));
511   DALI_TEST_EQUAL(actor.GetProperty(actor.GetPropertyIndex("isThisTheRealLife")).Get<bool>(), true);
512   DALI_TEST_EQUAL(actor.GetProperty(actor.GetPropertyIndex("isThisJustFantasy")).Get<bool>(), false);
513   DALI_TEST_EQUAL(actor.GetProperty(actor.GetPropertyIndex("velocity")).Get<Vector3>(), Vector3(.1f, 58.f, -.2f));
514   DALI_TEST_EQUAL(actor.GetProperty(actor.GetPropertyIndex("frameOfReference")).Get<Matrix>(), Matrix::IDENTITY);
515
516   END_TEST;
517 }
518
519 int UtcDaliDliLoaderLoadSceneConstraints(void)
520 {
521   Context ctx;
522
523   auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/constraints.dli";
524   DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output));
525   DALI_TEST_EQUAL(ctx.errors.size(), 1u);
526   DALI_TEST_CHECK(ctx.errors[0].find("invalid", ctx.errors[0].find("node ID")) != std::string::npos);
527
528   auto& scene = ctx.scene;
529   auto& roots = scene.GetRoots();
530   DALI_TEST_EQUAL(roots.size(), 1u);
531   DALI_TEST_EQUAL(scene.GetNode(0)->mName, "root");
532   DALI_TEST_EQUAL(scene.GetNode(1)->mName, "Alice");
533   DALI_TEST_EQUAL(scene.GetNode(2)->mName, "Bob");
534   DALI_TEST_EQUAL(scene.GetNode(3)->mName, "Charlie");
535
536   DALI_TEST_EQUAL(scene.GetNodeCount(), 4u);
537
538   ViewProjection viewProjection;
539   Transforms     xforms{
540     MatrixStack{},
541     viewProjection};
542   auto&                        resources = ctx.resources;
543   NodeDefinition::CreateParams nodeParams{
544     resources,
545     xforms,
546   };
547
548   Customization::Choices choices;
549
550   TestApplication app;
551
552   Actor root    = scene.CreateNodes(0, choices, nodeParams);
553   Actor alice   = root.FindChildByName("Alice");
554   Actor bob     = root.FindChildByName("Bob");
555   Actor charlie = root.FindChildByName("Charlie");
556
557   DALI_TEST_EQUAL(nodeParams.mConstrainables.size(), 3u);
558   DALI_TEST_EQUAL(bob.GetProperty(bob.GetPropertyIndex("angularVelocity")).Get<Vector2>(), Vector2(-0.5, 0.0004));
559
560   ctx.errors.clear();
561   scene.ApplyConstraints(root, std::move(nodeParams.mConstrainables), ctx.onError);
562   DALI_TEST_CHECK(ctx.errors.empty());
563
564   app.GetScene().Add(root);
565   app.SendNotification();
566   app.Render();
567   app.SendNotification();
568   app.Render();
569
570   DALI_TEST_EQUAL(charlie.GetCurrentProperty(Actor::Property::ORIENTATION), alice.GetProperty(Actor::Property::ORIENTATION));
571   DALI_TEST_EQUAL(charlie.GetCurrentProperty(Actor::Property::POSITION), bob.GetProperty(Actor::Property::POSITION));
572   DALI_TEST_EQUAL(charlie.GetCurrentProperty(charlie.GetPropertyIndex("angularVelocity")), bob.GetProperty(bob.GetPropertyIndex("angularVelocity")));
573
574   END_TEST;
575 }
576
577 int UtcDaliDliLoaderNodeProcessor(void)
578 {
579   Context ctx;
580
581   std::vector<Property::Map> nodeMaps;
582   ctx.input.mNodePropertyProcessor = [&](const NodeDefinition&, Property::Map&& map, StringCallback)
583   {
584     nodeMaps.push_back(map);
585   };
586
587   auto path = ctx.pathProvider(ResourceType::Mesh) + "dli/node-processor.dli";
588   DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output));
589
590   DALI_TEST_EQUAL(nodeMaps.size(), 2u);
591   DALI_TEST_EQUAL(nodeMaps[0].Count(), 5u);
592   DALI_TEST_EQUAL(nodeMaps[0].Find("name")->Get<std::string>(), "rootA");
593   DALI_TEST_EQUAL(nodeMaps[0].Find("nickname")->Get<std::string>(), "same as name");
594   DALI_TEST_EQUAL(nodeMaps[0].Find("favourite number")->Get<int32_t>(), 63478);
595
596   auto propArray = nodeMaps[0].Find("array");
597   DALI_TEST_EQUAL(propArray->GetType(), Property::ARRAY);
598
599   auto array = propArray->GetArray();
600   DALI_TEST_EQUAL(array->Count(), 5);
601   DALI_TEST_EQUAL(array->GetElementAt(0).Get<int32_t>(), 1);
602   DALI_TEST_EQUAL(array->GetElementAt(1).Get<int32_t>(), 2);
603   DALI_TEST_EQUAL(array->GetElementAt(2).Get<int32_t>(), 4);
604   DALI_TEST_EQUAL(array->GetElementAt(3).Get<int32_t>(), 8);
605   DALI_TEST_EQUAL(array->GetElementAt(4).Get<int32_t>(), -500);
606
607   auto propObject = nodeMaps[0].Find("object");
608   DALI_TEST_EQUAL(propObject->GetType(), Property::MAP);
609
610   auto object = propObject->GetMap();
611   DALI_TEST_EQUAL(object->Count(), 5);
612   DALI_TEST_EQUAL(object->Find("physics")->Get<bool>(), true);
613   DALI_TEST_EQUAL(object->Find("elasticity")->Get<float>(), .27f);
614   DALI_TEST_EQUAL(object->Find("drag")->Get<float>(), .91f);
615
616   auto propInnerArray = object->Find("inner array");
617   DALI_TEST_EQUAL(propInnerArray->GetType(), Property::ARRAY);
618
619   auto innerArray = propInnerArray->GetArray();
620   DALI_TEST_EQUAL(innerArray->Count(), 3);
621   DALI_TEST_EQUAL(innerArray->GetElementAt(0).Get<std::string>(), "why");
622   DALI_TEST_EQUAL(innerArray->GetElementAt(1).Get<std::string>(), "not");
623   DALI_TEST_EQUAL(innerArray->GetElementAt(2).Get<bool>(), false);
624
625   auto propInnerObject = object->Find("inner object");
626   DALI_TEST_EQUAL(propInnerObject->GetType(), Property::MAP);
627
628   auto innerObject = propInnerObject->GetMap();
629   DALI_TEST_EQUAL(innerObject->Count(), 1);
630   DALI_TEST_EQUAL(innerObject->Find("supported")->Get<bool>(), true);
631
632   DALI_TEST_EQUAL(nodeMaps[1].Count(), 1u);
633   DALI_TEST_EQUAL(nodeMaps[1].Find("name")->Get<std::string>(), "rootB");
634
635   END_TEST;
636 }
637
638 int UtcDaliDliLoaderLoadCoverageTest(void)
639 {
640   Context ctx;
641
642   auto path = ctx.pathProvider(ResourceType::Mesh) + "coverageTest.dli";
643   DALI_TEST_CHECK(ctx.loader.LoadModel(path, ctx.output));
644   DALI_TEST_CHECK(ctx.errors.empty());
645
646   auto& scene = ctx.scene;
647   auto& roots = scene.GetRoots();
648   DALI_TEST_EQUAL(roots.size(), 1u);
649   DALI_TEST_EQUAL(scene.GetNode(roots[0])->mName, "root");
650
651   DALI_TEST_EQUAL(scene.GetNodeCount(), 1u);
652
653   auto& resources = ctx.resources;
654   DALI_TEST_EQUAL(resources.mMeshes.size(), 1u);
655   DALI_TEST_EQUAL(resources.mShaders.size(), 1u);
656   DALI_TEST_EQUAL(resources.mEnvironmentMaps.size(), 2u);
657   DALI_TEST_EQUAL(resources.mSkeletons.size(), 0u);
658
659   auto& materials = ctx.resources.mMaterials;
660   DALI_TEST_EQUAL(2u, materials.size());
661
662   auto  iMaterial = materials.begin();
663   auto& md        = iMaterial->first;
664   DALI_TEST_EQUAL(md.mTextureStages.size(), 1u);
665
666   auto iTexture = md.mTextureStages.begin();
667   DALI_TEST_CHECK(MaskMatch(iTexture->mSemantic, MaterialDefinition::OCCLUSION));
668   DALI_TEST_EQUAL(iTexture->mTexture.mImageUri, "exercise/Icons/Icon_Idle.png");
669   ++iTexture;
670
671   DALI_TEST_EQUAL(ctx.cameraParameters.size(), 1u);
672   DALI_TEST_EQUAL(ctx.lights.size(), 1u);
673   DALI_TEST_EQUAL(ctx.animations.size(), 0u);
674   DALI_TEST_EQUAL(ctx.animGroups.size(), 0u);
675
676   ViewProjection viewProjection;
677   Transforms     xforms{
678     MatrixStack{},
679     viewProjection};
680   NodeDefinition::CreateParams nodeParams{
681     resources,
682     xforms,
683   };
684
685   Customization::Choices choices;
686
687   TestApplication app;
688
689   Actor root = Actor::New();
690   SetActorCentered(root);
691   for(auto iRoot : scene.GetRoots())
692   {
693     auto resourceRefs = resources.CreateRefCounter();
694     scene.CountResourceRefs(iRoot, choices, resourceRefs);
695     resources.mReferenceCounts = std::move(resourceRefs);
696     resources.CountEnvironmentReferences();
697     resources.LoadResources(ctx.pathProvider);
698     if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
699     {
700       scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
701       scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
702       ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
703       scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
704       root.Add(actor);
705     }
706   }
707
708   DALI_TEST_EQUAL(root.GetChildCount(), 1u);
709   DALI_TEST_EQUAL(root.GetChildAt(0).GetProperty(Actor::Property::NAME).Get<std::string>(), "root");
710
711   END_TEST;
712 }