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