{
struct Context
{
- ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type) {
+ ResourceBundle::PathProvider pathProvider = [](ResourceType::Value type)
+ {
return TEST_RESOURCE_DIR "/";
};
ShaderDefinitionFactory sdf;
sdf.SetResources(ctx.resources);
+ InitializeGltfLoader();
DALI_TEST_THROW(LoadGltfScene("non-existent.gltf", sdf, ctx.loadResult),
std::runtime_error,
ExceptionMessageStartsWith{"Failed to load"});
ShaderDefinitionFactory sdf;
sdf.SetResources(ctx.resources);
+ InitializeGltfLoader();
DALI_TEST_THROW(LoadGltfScene(TEST_RESOURCE_DIR "/invalid.gltf", sdf, ctx.loadResult),
std::runtime_error,
ExceptionMessageStartsWith{"Failed to parse"});
ShaderDefinitionFactory sdf;
sdf.SetResources(ctx.resources);
+ InitializeGltfLoader();
LoadGltfScene(TEST_RESOURCE_DIR "/AnimatedCube.gltf", sdf, ctx.loadResult);
DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
auto& materials = ctx.resources.mMaterials;
DALI_TEST_EQUAL(2u, materials.size());
const MaterialDefinition materialGroundTruth[]{
- {MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
- MaterialDefinition::NORMAL | MaterialDefinition::SPECULAR | MaterialDefinition::SPECULAR_COLOR |
- (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
- 0,
- Color::WHITE,
- 1.f,
- 0.f,
- Vector4(1.000, 0.766, 0.336, 1.0),
- 1.f,
- 1.f,
- Vector3(0.2, 0.1, 0.0),
- 0.0f,
- 0.5f,
- Vector3(0, 0, 1),
- true,
- false,
- true,
- false,
- true,
- true,
- {
- {MaterialDefinition::ALBEDO,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- {MaterialDefinition::NORMAL,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- {MaterialDefinition::OCCLUSION,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- {MaterialDefinition::EMISSIVE,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- {MaterialDefinition::SPECULAR,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- {MaterialDefinition::SPECULAR_COLOR,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- }},
- {MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
- MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
- MaterialDefinition::NORMAL | MaterialDefinition::GLTF_CHANNELS,
- 0,
- Color::WHITE,
- 1.f,
- 0.f,
- Vector4(1.000, 0.766, 0.336, 1.0),
- 1.f,
- 1.f,
- Vector3(0.2, 0.1, 0.0),
- 0.04f,
- 1.0f,
- Vector3::ONE,
- true,
- true,
- true,
- false,
- true,
- false,
- {
- {MaterialDefinition::ALBEDO,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- {MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
- {"AnimatedCube_MetallicRoughness.png",
- SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::NEAREST}},
- {MaterialDefinition::NORMAL,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- {MaterialDefinition::OCCLUSION,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- {MaterialDefinition::EMISSIVE,
- {"AnimatedCube_BaseColor.png",
- SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
- ImageDimensions(256, 256),
- SamplingMode::BOX_THEN_NEAREST}},
- }},
+ {
+ nullptr,
+ MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
+ MaterialDefinition::NORMAL | MaterialDefinition::SPECULAR | MaterialDefinition::SPECULAR_COLOR |
+ (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
+ 0,
+ Color::WHITE,
+ 1.f,
+ 0.f,
+ Vector4(1.000, 0.766, 0.336, 1.0),
+ 1.f,
+ 1.f,
+ Vector3(0.2, 0.1, 0.0),
+ 0.0f,
+ 0.5f,
+ Vector3(0, 0, 1),
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ {
+ {
+ MaterialDefinition::ALBEDO,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::NORMAL,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::OCCLUSION,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::EMISSIVE,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::SPECULAR,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::SPECULAR_COLOR,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ },
+ },
+ {
+ nullptr,
+ MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
+ MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION | MaterialDefinition::NORMAL |
+ MaterialDefinition::GLTF_CHANNELS,
+ 0,
+ Color::WHITE,
+ 1.f,
+ 0.f,
+ Vector4(1.000, 0.766, 0.336, 1.0),
+ 1.f,
+ 1.f,
+ Vector3(0.2, 0.1, 0.0),
+ 0.04f,
+ 1.0f,
+ Vector3::ONE,
+ true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ {
+ {
+ MaterialDefinition::ALBEDO,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+ {
+ "AnimatedCube_MetallicRoughness.png",
+ SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::NORMAL,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::OCCLUSION,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ {
+ MaterialDefinition::EMISSIVE,
+ {
+ "AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT),
+ ImageDimensions(256, 256),
+ SamplingMode::BOX_THEN_NEAREST,
+ },
+ },
+ },
+ },
};
auto iMaterial = materials.begin();
using Accessor = MeshDefinition::Accessor;
const MeshDefinition meshGroundTruth[]{
{
+ nullptr,
0,
Geometry::TRIANGLES,
"AnimatedCube.bin",
Accessor{Blob{0, 0}, {}},
},
{
+ nullptr,
0,
Geometry::TRIANGLES,
"AnimatedCube.bin",
int UtcDaliGltfLoaderSuccess2(void)
{
- Context ctx;
+ Context ctx;
ShaderDefinitionFactory sdf;
sdf.SetResources(ctx.resources);
+ InitializeGltfLoader();
LoadGltfScene(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", sdf, ctx.loadResult);
DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
TestApplication app;
const std::string resourcePath = TEST_RESOURCE_DIR "/";
- auto pathProvider = [resourcePath](ResourceType::Value) {
+ auto pathProvider = [resourcePath](ResourceType::Value)
+ {
return resourcePath;
};
sdf.SetResources(resources);
printf("%s\n", modelName);
+ InitializeGltfLoader();
LoadGltfScene(resourcePath + modelName + ".gltf", sdf, ctx.loadResult);
DALI_TEST_CHECK(ctx.scene.GetNodeCount() > 0);
sdf.SetResources(ctx.resources);
auto& resources = ctx.resources;
+ InitializeGltfLoader();
LoadGltfScene(TEST_RESOURCE_DIR "/MRendererTest.gltf", sdf, ctx.loadResult);
auto& scene = ctx.scene;
END_TEST;
}
-
int UtcDaliGltfLoaderAnimationLoadingTest(void)
{
Context ctx;
sdf.SetResources(ctx.resources);
auto& resources = ctx.resources;
+ InitializeGltfLoader();
LoadGltfScene(TEST_RESOURCE_DIR "/BoxAnimated.gltf", sdf, ctx.loadResult);
auto& scene = ctx.scene;
#include <dali-toolkit/devel-api/focus-manager/keyboard-focus-manager-devel.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <toolkit-event-thread-callback.h>
#include <dali-scene3d/public-api/controls/model/model.h>
gFocusChangedCallBackCalled = true;
}
+// For ResourceReady
+static bool gOnRelayoutCallBackCalled = false;
+void OnRelayoutCallback(Actor actor)
+{
+ gOnRelayoutCallBackCalled = true;
+}
+
+static bool gResourceReadyCalled = false;
+void OnResourceReady(Control control)
+{
+ gResourceReadyCalled = true;
+}
+
} // namespace
// Negative test case for a method
ToolkitTestApplication application;
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
uint32_t modelCount = model.GetModelRoot().GetChildCount();
DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION);
-
END_TEST;
}
ToolkitTestApplication application;
Scene3D::Model model = Scene3D::Model::New(TEST_DLI_FILE_NAME);
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
uint32_t modelCount = model.GetModelRoot().GetChildCount();
DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION);
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
Vector3 naturalSize = model.GetNaturalSize();
+ DALI_TEST_EQUALS(Vector3::ZERO, naturalSize, TEST_LOCATION);
+
+ application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
+ naturalSize = model.GetNaturalSize();
DALI_TEST_EQUALS(Vector3(2, 2, 2), naturalSize, TEST_LOCATION);
Actor root = model.GetModelRoot();
ToolkitTestApplication application;
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Actor meshActor = model.FindChildByName("AnimatedCube");
DALI_TEST_CHECK(meshActor);
Texture diffuseTexture = textureSet.GetTexture(7u);
Texture specularTexture = textureSet.GetTexture(8u);
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
model.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Texture newDiffuseTexture = textureSet.GetTexture(7u);
Texture newSpecularTexture = textureSet.GetTexture(8u);
DALI_TEST_NOT_EQUALS(diffuseTexture, newDiffuseTexture, 0.0f, TEST_LOCATION);
DALI_TEST_NOT_EQUALS(specularTexture, newSpecularTexture, 0.0f, TEST_LOCATION);
+ model.Unparent();
+ model.Reset();
END_TEST;
}
ToolkitTestApplication application;
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Actor meshActor = model.FindChildByName("AnimatedCube");
DALI_TEST_CHECK(meshActor);
Texture diffuseTexture = textureSet.GetTexture(7u);
Texture specularTexture = textureSet.GetTexture(8u);
+ // if url is empty, loading is not requested.
model.SetImageBasedLightSource("", "");
Texture newDiffuseTexture = textureSet.GetTexture(7u);
ToolkitTestApplication application;
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Actor meshActor = model.FindChildByName("AnimatedCube");
DALI_TEST_CHECK(meshActor);
Texture diffuseTexture = textureSet.GetTexture(7u);
Texture specularTexture = textureSet.GetTexture(8u);
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
model.SetImageBasedLightSource("dummy.ktx", "dummy.ktx");
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Texture newDiffuseTexture = textureSet.GetTexture(7u);
Texture newSpecularTexture = textureSet.GetTexture(8u);
END_TEST;
}
+int UtcDaliModelSetImageBasedLightSource04(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+ model.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+ application.GetScene().Add(model);
+
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+ END_TEST;
+}
+
int UtcDaliModelImageBasedFactor(void)
{
ToolkitTestApplication application;
// Allow children actor's event before on scene.
view.SetChildrenSensitive(true);
DALI_TEST_EQUALS(view.GetChildrenSensitive(), true, TEST_LOCATION);
-
application.GetScene().Add(view);
+ gResourceReadyCalled = false;
+ view.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Actor meshActor = view.FindChildByName("AnimatedCube");
DALI_TEST_CHECK(meshActor);
// Block children actor's event before on scene.
view.SetChildrenSensitive(false);
DALI_TEST_EQUALS(view.GetChildrenSensitive(), false, TEST_LOCATION);
-
application.GetScene().Add(view);
+ gResourceReadyCalled = false;
+ view.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Actor meshActor = view.FindChildByName("AnimatedCube");
DALI_TEST_CHECK(meshActor);
// Allow children actor's focus before on scene.
view.SetChildrenFocusable(true);
DALI_TEST_EQUALS(view.GetChildrenFocusable(), true, TEST_LOCATION);
-
application.GetScene().Add(view);
+ gResourceReadyCalled = false;
+ view.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Actor meshActor = view.FindChildByName("AnimatedCube");
DALI_TEST_CHECK(meshActor);
// Block children actor's focus before on scene.
view.SetChildrenFocusable(false);
DALI_TEST_EQUALS(view.GetChildrenFocusable(), false, TEST_LOCATION);
-
application.GetScene().Add(view);
+ gResourceReadyCalled = false;
+ view.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Actor meshActor = view.FindChildByName("AnimatedCube");
DALI_TEST_CHECK(meshActor);
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
uint32_t animationCount = model.GetAnimationCount();
DALI_TEST_EQUALS(1, animationCount, TEST_LOCATION);
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_ANIMATION_TEST_FILE_NAME);
model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
Scene3D::Model model = Scene3D::Model::New(TEST_DLI_EXERCISE_FILE_NAME);
model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
uint32_t animationCount = model.GetAnimationCount();
DALI_TEST_EQUALS(18, animationCount, TEST_LOCATION);
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_MULTIPLE_PRIMITIVE_FILE_NAME);
model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
model.SetProperty(Dali::Actor::Property::COLOR, Color::RED);
-
application.GetScene().Add(model);
+ gResourceReadyCalled = false;
+ model.ResourceReadySignal().Connect(&OnResourceReady);
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
application.SendNotification();
application.Render();
END_TEST;
}
-
-// For ResourceReady
-namespace
-{
-static bool gOnRelayoutCallBackCalled = false;
-void OnRelayoutCallback(Actor actor)
-{
- gOnRelayoutCallBackCalled = true;
-}
-
-static bool gResourceReadyCalled = false;
-void OnResourceReady(Control control)
-{
- gResourceReadyCalled = true;
-}
-} // namespace
-
int UtcDaliModelResourceReady(void)
{
ToolkitTestApplication application;
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
DALI_TEST_EQUALS(gOnRelayoutCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(model.IsResourceReady(), true, TEST_LOCATION);
DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
+#include <toolkit-event-thread-callback.h>
using namespace Dali;
using namespace Dali::Toolkit;
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-const char* TEST_DIFFUSE_TEXTURE = TEST_RESOURCE_DIR "/forest_irradiance.ktx";
-const char* TEST_SPECULAR_TEXTURE = TEST_RESOURCE_DIR "/forest_radiance.ktx";
+const char* TEST_EQUIRECTANGULAR_TEXTURE = TEST_RESOURCE_DIR "/application-icon-20.png";
+const char* TEST_DIFFUSE_TEXTURE = TEST_RESOURCE_DIR "/forest_irradiance.ktx";
+const char* TEST_SPECULAR_TEXTURE = TEST_RESOURCE_DIR "/forest_radiance.ktx";
+const char* TEST_DIFFUSE_TEXTURE2 = TEST_RESOURCE_DIR "//forest_irradiance.ktx";
+const char* TEST_SPECULAR_TEXTURE2 = TEST_RESOURCE_DIR "//forest_radiance.ktx";
Dali::Texture GetDiffuseTexture(Dali::Scene3D::Model model)
{
return texture;
}
+
+
+// For ResourceReady
+static bool gOnRelayoutCallBackCalled = false;
+void OnRelayoutCallback(Actor actor)
+{
+ gOnRelayoutCallBackCalled = true;
+}
+
+static bool gResourceReadyCalled = false;
+void OnResourceReady(Control control)
+{
+ gResourceReadyCalled = true;
+}
} // namespace
// Negative test case for a method
ToolkitTestApplication application;
Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.ResourceReadySignal().Connect(OnResourceReady);
view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
application.GetScene().Add(view);
view.Add(modelView1);
view.Add(modelView2);
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), GetDiffuseTexture(modelView2), 0.0f, TEST_LOCATION);
DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), GetSpecularTexture(modelView2), 0.0f, TEST_LOCATION);
DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), GetDiffuseTexture(modelView3), 0.0f, TEST_LOCATION);
DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), GetSpecularTexture(modelView3), 0.0f, TEST_LOCATION);
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
DALI_TEST_EQUALS(GetDiffuseTexture(modelView1), GetDiffuseTexture(modelView2), TEST_LOCATION);
DALI_TEST_EQUALS(GetSpecularTexture(modelView1), GetSpecularTexture(modelView2), TEST_LOCATION);
DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), GetDiffuseTexture(modelView3), 0.0f, TEST_LOCATION);
DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), GetSpecularTexture(modelView3), 0.0f, TEST_LOCATION);
view.Add(modelView3);
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
DALI_TEST_EQUALS(GetDiffuseTexture(modelView1), GetDiffuseTexture(modelView3), TEST_LOCATION);
DALI_TEST_EQUALS(GetSpecularTexture(modelView1), GetSpecularTexture(modelView3), TEST_LOCATION);
view.Remove(modelView1);
- view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+ view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE2, TEST_SPECULAR_TEXTURE2);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), GetDiffuseTexture(modelView2), 0.0f, TEST_LOCATION);
DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), GetSpecularTexture(modelView2), 0.0f, TEST_LOCATION);
ToolkitTestApplication application;
Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.ResourceReadySignal().Connect(OnResourceReady);
view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
application.GetScene().Add(view);
application.Render();
Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+ modelView1.ResourceReadySignal().Connect(OnResourceReady);
view.Add(modelView1);
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
Dali::Texture diffuseTexture = GetDiffuseTexture(modelView1);
Dali::Texture specularTexture = GetSpecularTexture(modelView1);
- modelView1.SetImageBasedLightSource(TEST_SPECULAR_TEXTURE, TEST_DIFFUSE_TEXTURE);
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+ modelView1.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE2, TEST_SPECULAR_TEXTURE2);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), diffuseTexture, 0.0f, TEST_LOCATION);
DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), specularTexture, 0.0f, TEST_LOCATION);
diffuseTexture = GetDiffuseTexture(modelView1);
Scene3D::SceneView view = Scene3D::SceneView::New();
view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
-
+ view.ResourceReadySignal().Connect(OnResourceReady);
application.GetScene().Add(view);
application.SendNotification();
Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
view.Add(modelView1);
-
modelView1.SetImageBasedLightSource(TEST_SPECULAR_TEXTURE, TEST_DIFFUSE_TEXTURE);
+
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
Dali::Texture diffuseTexture = GetDiffuseTexture(modelView1);
Dali::Texture specularTexture = GetSpecularTexture(modelView1);
- view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+ view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE2, TEST_SPECULAR_TEXTURE2);
+
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
DALI_TEST_EQUALS(GetDiffuseTexture(modelView1), diffuseTexture, TEST_LOCATION);
DALI_TEST_EQUALS(GetSpecularTexture(modelView1), specularTexture, TEST_LOCATION);
END_TEST;
}
-// For ResourceReady
-namespace
-{
-static bool gOnRelayoutCallBackCalled = false;
-void OnRelayoutCallback(Actor actor)
-{
- gOnRelayoutCallBackCalled = true;
-}
-
-static bool gResourceReadyCalled = false;
-void OnResourceReady(Control control)
-{
- gResourceReadyCalled = true;
-}
-}
-
int UtcDaliSceneViewResourceReady(void)
{
ToolkitTestApplication application;
application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
DALI_TEST_EQUALS(gOnRelayoutCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
Scene3D::SceneView view = Scene3D::SceneView::New();
view.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
view.ResourceReadySignal().Connect(OnResourceReady);
- // SceneView::IsResourceReady() returns true by default.
- DALI_TEST_EQUALS(view.IsResourceReady(), true, TEST_LOCATION);
+ application.GetScene().Add(view);
- // Sanity check
- DALI_TEST_CHECK(!gResourceReadyCalled);
+ application.SendNotification();
+ application.Render();
+
+ uint32_t childCount = view.GetChildAt(0u).GetChildCount();
+ view.SetSkybox(TEST_SPECULAR_TEXTURE);
+
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(view.GetChildAt(0u).GetChildCount(), childCount + 1, TEST_LOCATION);
+
+ view.Unparent();
+ view.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliSceneViewSetSkyboxEquirectangular(void)
+{
+ ToolkitTestApplication application;
+
+ gResourceReadyCalled = false;
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ view.ResourceReadySignal().Connect(OnResourceReady);
application.GetScene().Add(view);
application.SendNotification();
application.Render();
- DALI_TEST_EQUALS(view.IsResourceReady(), true, TEST_LOCATION);
+ uint32_t childCount = view.GetChildAt(0u).GetChildCount();
+ view.SetSkybox(TEST_EQUIRECTANGULAR_TEXTURE, Scene3D::SceneView::SkyboxType::EQUIRECTANGULAR);
+
+ gResourceReadyCalled = false;
DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(view.GetChildAt(0u).GetChildCount(), childCount + 1, TEST_LOCATION);
+
+ view.Unparent();
+ view.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliSceneViewSetSkyboxEmpty(void)
+{
+ ToolkitTestApplication application;
+
gResourceReadyCalled = false;
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ view.ResourceReadySignal().Connect(OnResourceReady);
+ application.GetScene().Add(view);
- view.SetSkybox(TEST_SPECULAR_TEXTURE);
+ application.SendNotification();
+ application.Render();
+
+ uint32_t childCount = view.GetChildAt(0u).GetChildCount();
+ view.SetSkybox("");
+ DALI_TEST_EQUALS(view.GetChildAt(0u).GetChildCount(), childCount, TEST_LOCATION);
+
+ view.Unparent();
+ view.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliSceneViewSetSkyboxEquirectangularEmpty(void)
+{
+ ToolkitTestApplication application;
+
+ gResourceReadyCalled = false;
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ view.ResourceReadySignal().Connect(OnResourceReady);
+ application.GetScene().Add(view);
application.SendNotification();
application.Render();
- DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+ uint32_t childCount = view.GetChildAt(0u).GetChildCount();
+ view.SetSkybox("", Scene3D::SceneView::SkyboxType::EQUIRECTANGULAR);
+ DALI_TEST_EQUALS(view.GetChildAt(0u).GetChildCount(), childCount, TEST_LOCATION);
+
+ view.Unparent();
+ view.Reset();
END_TEST;
}
END_TEST;
}
+int UtcDaliSceneViewSetImageBasedLightAndSkybox(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.ResourceReadySignal().Connect(OnResourceReady);
+ view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
+ view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+ view.SetSkybox(TEST_SPECULAR_TEXTURE);
+ application.GetScene().Add(view);
+
+ // Check SceneView needs 3 trigger to load both of image based light and skybox.
+ gResourceReadyCalled = false;
+ DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliSceneViewCreateAndRemoveRenderTask(void)
{
ToolkitTestApplication application;
--- /dev/null
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/internal/common/environment-map-load-task.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/cube-map-loader.h>
+
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+
+EnvironmentMapLoadTask::EnvironmentMapLoadTask(const std::string& environmentMapUrl, CallbackBase* callback)
+: AsyncTask(callback),
+ mEnvironmentMapUrl(environmentMapUrl),
+ mIsReady(true),
+ mHasSucceeded(false)
+{
+}
+
+EnvironmentMapLoadTask::~EnvironmentMapLoadTask()
+{
+}
+
+void EnvironmentMapLoadTask::Process()
+{
+ mHasSucceeded = Scene3D::Loader::LoadCubeMapData(mEnvironmentMapUrl, mEnvironmentMapPixelData);
+}
+
+bool EnvironmentMapLoadTask::IsReady()
+{
+ return mIsReady;
+}
+
+bool EnvironmentMapLoadTask::HasSucceeded() const
+{
+ return mHasSucceeded;
+}
+
+Dali::Scene3D::Loader::CubeData EnvironmentMapLoadTask::GetEnvironmentMap() const
+{
+ Dali::Scene3D::Loader::CubeData environmentMapPixelData;
+ if(mIsReady && mHasSucceeded && !mEnvironmentMapPixelData.data.empty())
+ {
+ environmentMapPixelData = mEnvironmentMapPixelData;
+ }
+ return environmentMapPixelData;
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_ENVIRONMENT_MAP_LOAD_TASK_H
+#define DALI_SCENE3D_ENVIRONMENT_MAP_LOAD_TASK_H
+
+/*
+ * Copyright (c) 2022 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.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/images/pixel-data.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/load-result.h>
+#include <dali-scene3d/public-api/loader/scene-definition.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+class EnvironmentMapLoadTask;
+typedef IntrusivePtr<EnvironmentMapLoadTask> EnvironmentMapLoadTaskPtr;
+
+class EnvironmentMapLoadTask : public AsyncTask
+{
+public:
+ /**
+ * Constructor
+ * @param[in] environmentMapUrl The url of the environment map image file.
+ * @param[in] callback The callback that is called when the operation is completed.
+ */
+ EnvironmentMapLoadTask(const std::string& environmentMapUrl, CallbackBase* callback);
+
+ /**
+ * Destructor.
+ */
+ ~EnvironmentMapLoadTask();
+
+ /**
+ * Process the task
+ */
+ void Process() override;
+
+ /**
+ * Whether the task is ready to process.
+ * @return True if the task is ready to process.
+ */
+ bool IsReady() override;
+
+ /**
+ * Whether the task has succeeded.
+ * @return True if the task has succeeded.
+ */
+ bool HasSucceeded() const;
+
+ /**
+ * Retrieves loaded Environment Map
+ * @return CubeData loaded from url.
+ *
+ * TODO: Supports Equirectangular environment map
+ */
+ Dali::Scene3D::Loader::CubeData GetEnvironmentMap() const;
+
+private:
+ // Undefined
+ EnvironmentMapLoadTask(const EnvironmentMapLoadTask& task) = delete;
+
+ // Undefined
+ EnvironmentMapLoadTask& operator=(const EnvironmentMapLoadTask& task) = delete;
+
+private:
+ std::string mEnvironmentMapUrl;
+ Dali::Scene3D::Loader::CubeData mEnvironmentMapPixelData;
+
+ bool mIsReady;
+ bool mHasSucceeded;
+};
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_ENVIRONMENT_MAP_LOAD_TASK_H
--- /dev/null
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/internal/common/model-load-task.h>
+
+// EXTERNAL INCLUDES
+#include <filesystem>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/animation-definition.h>
+#include <dali-scene3d/public-api/loader/camera-parameters.h>
+#include <dali-scene3d/public-api/loader/cube-map-loader.h>
+#include <dali-scene3d/public-api/loader/dli-loader.h>
+#include <dali-scene3d/public-api/loader/gltf2-loader.h>
+#include <dali-scene3d/public-api/loader/light-parameters.h>
+#include <dali-scene3d/public-api/loader/node-definition.h>
+#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
+
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+namespace
+{
+static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f);
+
+static constexpr std::string_view OBJ_EXTENSION = ".obj";
+static constexpr std::string_view GLTF_EXTENSION = ".gltf";
+static constexpr std::string_view DLI_EXTENSION = ".dli";
+static constexpr std::string_view METADATA_EXTENSION = "metadata";
+} // namespace
+
+ModelLoadTask::ModelLoadTask(const std::string& modelUrl, const std::string& resourceDirectoryUrl, CallbackBase* callback)
+: AsyncTask(callback),
+ mModelUrl(modelUrl),
+ mResourceDirectoryUrl(resourceDirectoryUrl),
+ mHasSucceeded(false)
+{
+}
+
+ModelLoadTask::~ModelLoadTask()
+{
+}
+
+void ModelLoadTask::Process()
+{
+ std::filesystem::path modelUrl(mModelUrl);
+ if(mResourceDirectoryUrl.empty())
+ {
+ mResourceDirectoryUrl = std::string(modelUrl.parent_path()) + "/";
+ }
+ std::string extension = modelUrl.extension();
+ std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
+
+ Dali::Scene3D::Loader::ResourceBundle::PathProvider pathProvider = [&](Dali::Scene3D::Loader::ResourceType::Value type)
+ {
+ return mResourceDirectoryUrl;
+ };
+ mAnimations.clear();
+
+ std::filesystem::path metaDataUrl = modelUrl;
+ metaDataUrl.replace_extension(METADATA_EXTENSION.data());
+
+ Dali::Scene3D::Loader::LoadSceneMetadata(metaDataUrl.c_str(), mMetaData);
+
+ Dali::Scene3D::Loader::LoadResult result{mResources, mScene, mMetaData, mAnimations, mAnimGroups, mCameraParameters, mLights};
+
+ if(extension == DLI_EXTENSION)
+ {
+ Dali::Scene3D::Loader::DliLoader loader;
+ Dali::Scene3D::Loader::DliLoader::InputParams input{
+ pathProvider(Dali::Scene3D::Loader::ResourceType::Mesh),
+ nullptr,
+ {},
+ {},
+ nullptr,
+ {}};
+ Dali::Scene3D::Loader::DliLoader::LoadParams loadParams{input, result};
+ if(!loader.LoadScene(mModelUrl, loadParams))
+ {
+ DALI_LOG_ERROR("Failed to load scene from '%s': %s\n", mModelUrl.c_str(), loader.GetParseError().c_str());
+ return;
+ }
+ }
+ else if(extension == GLTF_EXTENSION)
+ {
+ Dali::Scene3D::Loader::ShaderDefinitionFactory sdf;
+ sdf.SetResources(mResources);
+ Dali::Scene3D::Loader::LoadGltfScene(mModelUrl, sdf, result);
+ }
+ else
+ {
+ DALI_LOG_ERROR("Unsupported model type.\n");
+ return;
+ }
+
+ for(auto iRoot : mScene.GetRoots())
+ {
+ mResourceRefCounts.push_back(mResources.CreateRefCounter());
+ mScene.CountResourceRefs(iRoot, mResourceChoices, mResourceRefCounts.back());
+ mResources.CountEnvironmentReferences(mResourceRefCounts.back());
+
+ mResources.LoadRawResources(mResourceRefCounts.back(), pathProvider);
+
+ // glTF Mesh is defined in right hand coordinate system, with positive Y for Up direction.
+ // Because DALi uses left hand system, Y direciton will be flipped for environment map sampling.
+ for(auto&& env : mResources.mEnvironmentMaps)
+ {
+ env.first.mYDirection = Y_DIRECTION;
+ }
+ }
+ mHasSucceeded = true;
+}
+
+bool ModelLoadTask::IsReady()
+{
+ return true;
+}
+
+bool ModelLoadTask::HasSucceeded() const
+{
+ return mHasSucceeded;
+}
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_SCENE3D_MODEL_LOAD_TASK_H
+#define DALI_SCENE3D_MODEL_LOAD_TASK_H
+
+/*
+ * Copyright (c) 2022 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.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/images/pixel-data.h>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/loader/load-result.h>
+#include <dali-scene3d/public-api/loader/scene-definition.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+class ModelLoadTask;
+typedef IntrusivePtr<ModelLoadTask> ModelLoadTaskPtr;
+
+class ModelLoadTask : public AsyncTask
+{
+public:
+ /**
+ * Constructor
+ * @param[in] modelUrl model file path.(e.g., glTF, and DLI).
+ * @param[in] resourceDirectoryUrl resource file path that includes binary, image etc.
+ * @param[in] callback The callback that is called when the operation is completed.
+ */
+ ModelLoadTask(const std::string& modelUrl, const std::string& resourceDirectoryUrl, CallbackBase* callback);
+
+ /**
+ * Destructor.
+ */
+ ~ModelLoadTask();
+
+ /**
+ * Process the task
+ */
+ void Process() override;
+
+ /**
+ * Whether the task is ready to process.
+ * @return True if the task is ready to process.
+ */
+ bool IsReady() override;
+
+ /**
+ * Whether the task has succeeded.
+ * @return True if the task has succeeded.
+ */
+ bool HasSucceeded() const;
+
+private:
+ // Undefined
+ ModelLoadTask(const ModelLoadTask& task) = delete;
+
+ // Undefined
+ ModelLoadTask& operator=(const ModelLoadTask& task) = delete;
+
+public:
+ std::string mModelUrl;
+ std::string mResourceDirectoryUrl;
+
+ Dali::Scene3D::Loader::ResourceBundle mResources;
+ Dali::Scene3D::Loader::SceneDefinition mScene;
+ Dali::Scene3D::Loader::SceneMetadata mMetaData;
+ std::vector<Dali::Scene3D::Loader::AnimationGroupDefinition> mAnimGroups;
+ std::vector<Dali::Scene3D::Loader::CameraParameters> mCameraParameters;
+ std::vector<Dali::Scene3D::Loader::LightParameters> mLights;
+ std::vector<Dali::Scene3D::Loader::AnimationDefinition> mAnimations;
+
+ Dali::Scene3D::Loader::Customization::Choices mResourceChoices;
+ std::vector<Dali::Scene3D::Loader::ResourceRefCounts> mResourceRefCounts;
+ bool mHasSucceeded;
+};
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_MODEL_LOAD_TASK_H
#include <dali/public-api/math/math-utils.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <filesystem>
// INTERNAL INCLUDES
static constexpr bool DEFAULT_MODEL_CHILDREN_SENSITIVE = false;
static constexpr bool DEFAULT_MODEL_CHILDREN_FOCUSABLE = false;
-static constexpr std::string_view KTX_EXTENSION = ".ktx";
-static constexpr std::string_view OBJ_EXTENSION = ".obj";
-static constexpr std::string_view GLTF_EXTENSION = ".gltf";
-static constexpr std::string_view DLI_EXTENSION = ".dli";
-
struct BoundingVolume
{
void Init()
mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE),
mModelChildrenFocusable(DEFAULT_MODEL_CHILDREN_FOCUSABLE),
mModelResourceReady(false),
- mIBLResourceReady(true)
+ mIblDiffuseResourceReady(true),
+ mIblSpecularResourceReady(true),
+ mIblDiffuseDirty(false),
+ mIblSpecularDirty(false)
{
}
Model::~Model()
{
+ ResetResourceTasks();
}
Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
{
- mIBLResourceReady = false;
- Texture diffuseTexture = (!diffuseUrl.empty()) ? Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl) : Texture();
- Texture specularTexture = (!specularUrl.empty()) ? Dali::Scene3D::Loader::LoadCubeMap(specularUrl) : Texture();
- SetImageBasedLightTexture(diffuseTexture, specularTexture, scaleFactor);
- mIBLResourceReady = true;
+ bool needIblReset = false;
+ bool isOnScene = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
+ if(mDiffuseIblUrl != diffuseUrl)
+ {
+ mDiffuseIblUrl = diffuseUrl;
+ if(mDiffuseIblUrl.empty())
+ {
+ needIblReset = true;
+ }
+ else
+ {
+ mIblDiffuseDirty = true;
+ mIblDiffuseResourceReady = false;
+ }
+ }
+
+ if(mSpecularIblUrl != specularUrl)
+ {
+ mSpecularIblUrl = specularUrl;
+ if(mSpecularIblUrl.empty())
+ {
+ needIblReset = true;
+ }
+ else
+ {
+ mIblSpecularDirty = true;
+ mIblSpecularResourceReady = false;
+ }
+ }
+
+ // If one or both of diffuse url and specular url are empty,
+ // we don't need to request to load texture.
+ if(needIblReset)
+ {
+ if(mIblDiffuseLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
+ mIblDiffuseLoadTask.Reset();
+ }
+
+ if(mIblSpecularLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
+ mIblSpecularLoadTask.Reset();
+ }
+
+ mIblDiffuseDirty = false;
+ mIblSpecularDirty = false;
+ mIblDiffuseResourceReady = true;
+ mIblSpecularResourceReady = true;
+
+ mDiffuseTexture.Reset();
+ mSpecularTexture.Reset();
+ UpdateImageBasedLightTexture();
+ }
+ else
+ {
+ if(isOnScene && mIblDiffuseDirty)
+ {
+ if(mIblDiffuseLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
+ mIblDiffuseLoadTask.Reset();
+ }
+ mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, MakeCallback(this, &Model::OnIblDiffuseLoadComplete));
+ Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
+ mIblDiffuseDirty = false;
+ }
+
+ if(isOnScene && mIblSpecularDirty)
+ {
+ if(mIblSpecularLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
+ mIblSpecularLoadTask.Reset();
+ }
+ mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, MakeCallback(this, &Model::OnIblSpecularLoadComplete));
+ Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
+ mIblSpecularDirty = false;
+ }
+ }
+
+ if(!Dali::Equals(mIblScaleFactor, scaleFactor))
+ {
+ mIblScaleFactor = scaleFactor;
+ UpdateImageBasedLightScaleFactor();
+ }
- // If Model resource is already ready, then set resource ready.
- // If Model resource is still not ready, wait for model resource ready.
+ // If diffuse and specular textures are already loaded, emits resource ready signal here.
if(IsResourceReady())
{
- SetResourceReady(false);
+ Control::SetResourceReady(false);
}
}
void Model::OnSceneConnection(int depth)
{
- if(!mModelRoot)
+ if(!mModelLoadTask && !mModelRoot)
+ {
+ Scene3D::Loader::InitializeGltfLoader();
+ mModelLoadTask = new ModelLoadTask(mModelUrl, mResourceDirectoryUrl, MakeCallback(this, &Model::OnModelLoadComplete));
+ Dali::AsyncTaskManager::Get().AddTask(mModelLoadTask);
+ }
+ // If diffuse and specular url is not valid, IBL does not need to be loaded.
+ if(!mDiffuseIblUrl.empty() && !mSpecularIblUrl.empty())
{
- LoadModel();
+ SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
}
Actor parent = Self().GetParent();
{
if(!mModelRoot)
{
- LoadModel();
+ DALI_LOG_ERROR("Model is still not loaded.\n");
+ return Vector3::ZERO;
}
return mNaturalSize;
bool Model::IsResourceReady() const
{
- return mModelResourceReady && mIBLResourceReady;
+ return mModelResourceReady && mIblDiffuseResourceReady && mIblSpecularResourceReady;
}
-void Model::LoadModel()
+void Model::ScaleModel()
{
- std::filesystem::path modelUrl(mModelUrl);
- if(mResourceDirectoryUrl.empty())
+ if(mModelRoot)
{
- mResourceDirectoryUrl = std::string(modelUrl.parent_path()) + "/";
+ float scale = 1.0f;
+ Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+ if(size.x > 0.0f && size.y > 0.0f)
+ {
+ scale = MAXFLOAT;
+ scale = std::min(size.x / mNaturalSize.x, scale);
+ scale = std::min(size.y / mNaturalSize.y, scale);
+ }
+ // Models in glTF and dli are defined as right hand coordinate system.
+ // DALi uses left hand coordinate system. Scaling negative is for change winding order.
+ mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scale);
}
- std::string extension = modelUrl.extension();
- std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
+}
- Dali::Scene3D::Loader::ResourceBundle::PathProvider pathProvider = [&](Dali::Scene3D::Loader::ResourceType::Value type) {
- return mResourceDirectoryUrl;
- };
+void Model::FitModelPosition()
+{
+ if(mModelRoot)
+ {
+ // Loaded model pivot is not the model center.
+ mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
+ }
+}
- Dali::Scene3D::Loader::ResourceBundle resources;
- Dali::Scene3D::Loader::SceneDefinition scene;
- std::vector<Dali::Scene3D::Loader::AnimationGroupDefinition> animGroups;
- std::vector<Dali::Scene3D::Loader::CameraParameters> cameraParameters;
- std::vector<Dali::Scene3D::Loader::LightParameters> lights;
+void Model::CollectRenderableActor(Actor actor)
+{
+ uint32_t rendererCount = actor.GetRendererCount();
+ if(rendererCount)
+ {
+ mRenderableActors.push_back(actor);
+ }
- std::vector<Dali::Scene3D::Loader::AnimationDefinition> animations;
- animations.clear();
+ uint32_t childrenCount = actor.GetChildCount();
+ for(uint32_t i = 0; i < childrenCount; ++i)
+ {
+ CollectRenderableActor(actor.GetChildAt(i));
+ }
+}
- Dali::Scene3D::Loader::SceneMetadata metaData;
+void Model::UpdateImageBasedLightTexture()
+{
+ Dali::Texture currentDiffuseTexture = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
+ Dali::Texture currentSpecularTexture = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
+ float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
- std::filesystem::path metaDataUrl = modelUrl;
- metaDataUrl.replace_extension("metadata");
+ if(!currentDiffuseTexture || !currentSpecularTexture)
+ {
+ currentDiffuseTexture = mDefaultDiffuseTexture;
+ currentSpecularTexture = mDefaultSpecularTexture;
+ currentIblScaleFactor = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
+ }
- Dali::Scene3D::Loader::LoadSceneMetadata(metaDataUrl.c_str(), metaData);
+ for(auto&& actor : mRenderableActors)
+ {
+ Actor renderableActor = actor.GetHandle();
+ if(renderableActor)
+ {
+ uint32_t rendererCount = renderableActor.GetRendererCount();
+ for(uint32_t i = 0; i < rendererCount; ++i)
+ {
+ Dali::Renderer renderer = renderableActor.GetRendererAt(i);
+ if(renderer)
+ {
+ Dali::TextureSet textures = renderer.GetTextures();
+ if(textures)
+ {
+ uint32_t textureCount = textures.GetTextureCount();
+ // EnvMap requires at least 2 texture, diffuse and specular
+ if(textureCount > 2u)
+ {
+ textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, currentDiffuseTexture);
+ textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, currentSpecularTexture);
+ }
+ }
+ }
+ }
+ renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
+ }
+ }
+}
- Dali::Scene3D::Loader::LoadResult output{resources, scene, metaData, animations, animGroups, cameraParameters, lights};
+void Model::UpdateImageBasedLightScaleFactor()
+{
+ if((!mDiffuseTexture || !mSpecularTexture) &&
+ (!mSceneDiffuseTexture || !mSceneSpecularTexture))
+ {
+ return;
+ }
- if(extension == DLI_EXTENSION)
+ float currentIblScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
+ for(auto&& actor : mRenderableActors)
{
- Dali::Scene3D::Loader::DliLoader loader;
- Dali::Scene3D::Loader::DliLoader::InputParams input{
- pathProvider(Dali::Scene3D::Loader::ResourceType::Mesh),
- nullptr,
- {},
- {},
- nullptr,
- {}};
- Dali::Scene3D::Loader::DliLoader::LoadParams loadParams{input, output};
- if(!loader.LoadScene(mModelUrl, loadParams))
+ Actor renderableActor = actor.GetHandle();
+ if(renderableActor)
{
- Dali::Scene3D::Loader::ExceptionFlinger(ASSERT_LOCATION) << "Failed to load scene from '" << mModelUrl << "': " << loader.GetParseError();
+ renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
}
}
- else if(extension == GLTF_EXTENSION)
- {
- Dali::Scene3D::Loader::ShaderDefinitionFactory sdf;
- sdf.SetResources(resources);
- Dali::Scene3D::Loader::LoadGltfScene(mModelUrl, sdf, output);
+}
- resources.mEnvironmentMaps.push_back({});
+void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
+{
+ if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
+ {
+ mSceneDiffuseTexture = diffuseTexture;
+ mSceneSpecularTexture = specularTexture;
+ mSceneIblScaleFactor = scaleFactor;
+ // If Model IBL is not set, use SceneView's IBL.
+ if(!mDiffuseTexture || !mSpecularTexture)
+ {
+ UpdateImageBasedLightTexture();
+ }
}
- else
+}
+
+void Model::NotifyImageBasedLightScaleFactor(float scaleFactor)
+{
+ mSceneIblScaleFactor = scaleFactor;
+ if(mSceneDiffuseTexture && mSceneSpecularTexture)
{
- DALI_LOG_ERROR("Unsupported model type.\n");
+ UpdateImageBasedLightScaleFactor();
}
+}
- Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
- Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}};
- Dali::Scene3D::Loader::Customization::Choices choices;
+void Model::OnModelLoadComplete()
+{
+ if(!mModelLoadTask->HasSucceeded())
+ {
+ ResetResourceTasks();
+ return;
+ }
mModelRoot = Actor::New();
mModelRoot.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
- BoundingVolume AABB;
- for(auto iRoot : scene.GetRoots())
+ BoundingVolume AABB;
+ auto* resources = &(mModelLoadTask->mResources);
+ auto* scene = &(mModelLoadTask->mScene);
+ Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
+ Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{*resources, xforms, {}, {}, {}};
+ uint32_t rootCount = 0u;
+ for(auto iRoot : scene->GetRoots())
{
- auto resourceRefs = resources.CreateRefCounter();
- scene.CountResourceRefs(iRoot, choices, resourceRefs);
- resources.CountEnvironmentReferences(resourceRefs);
-
- resources.LoadResources(resourceRefs, pathProvider);
+ resources->GenerateResources(mModelLoadTask->mResourceRefCounts[rootCount]);
- // glTF Mesh is defined in right hand coordinate system, with positive Y for Up direction.
- // Because DALi uses left hand system, Y direciton will be flipped for environment map sampling.
- for(auto&& env : resources.mEnvironmentMaps)
+ if(auto actor = scene->CreateNodes(iRoot, mModelLoadTask->mResourceChoices, nodeParams))
{
- env.first.mYDirection = Y_DIRECTION;
- }
-
- if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams))
- {
- scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor);
- scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables));
- ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests));
+ scene->ConfigureSkeletonJoints(iRoot, resources->mSkeletons, actor);
+ scene->ConfigureSkinningShaders(*resources, actor, std::move(nodeParams.mSkinnables));
+ ConfigureBlendShapeShaders(*resources, *scene, actor, std::move(nodeParams.mBlendshapeRequests));
- scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
+ scene->ApplyConstraints(actor, std::move(nodeParams.mConstrainables));
mModelRoot.Add(actor);
}
- AddModelTreeToAABB(AABB, scene, choices, iRoot, nodeParams, Matrix::IDENTITY);
+ AddModelTreeToAABB(AABB, *scene, mModelLoadTask->mResourceChoices, iRoot, nodeParams, Matrix::IDENTITY);
+ rootCount++;
}
- if(!resources.mEnvironmentMaps.empty())
+ if(!resources->mEnvironmentMaps.empty())
{
- mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse;
- mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
+ mDefaultDiffuseTexture = resources->mEnvironmentMaps.front().second.mDiffuse;
+ mDefaultSpecularTexture = resources->mEnvironmentMaps.front().second.mSpecular;
}
- if(!animations.empty())
+ if(!mModelLoadTask->mAnimations.empty())
{
auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property)
{
Dali::Actor actor;
if(property.mNodeIndex != Scene3D::Loader::INVALID_INDEX)
{
- auto* node = scene.GetNode(property.mNodeIndex);
+ auto* node = scene->GetNode(property.mNodeIndex);
if(node != nullptr)
{
actor = mModelRoot.FindChildById(node->mNodeId);
};
mAnimations.clear();
- for(auto&& animation : animations)
+ for(auto&& animation : mModelLoadTask->mAnimations)
{
Dali::Animation anim = animation.ReAnimate(getActor);
mRenderableActors.clear();
CollectRenderableActor(mModelRoot);
+
UpdateImageBasedLightTexture();
UpdateImageBasedLightScaleFactor();
mModelResourceReady = true;
- Control::SetResourceReady(false);
-}
-
-void Model::ScaleModel()
-{
- if(mModelRoot)
+ if(IsResourceReady())
{
- float scale = 1.0f;
- Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
- if(size.x > 0.0f && size.y > 0.0f)
- {
- scale = MAXFLOAT;
- scale = std::min(size.x / mNaturalSize.x, scale);
- scale = std::min(size.y / mNaturalSize.y, scale);
- }
- // Models in glTF and dli are defined as right hand coordinate system.
- // DALi uses left hand coordinate system. Scaling negative is for change winding order.
- mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scale);
+ Control::SetResourceReady(false);
}
+ mModelLoadTask.Reset();
}
-void Model::FitModelPosition()
+void Model::OnIblDiffuseLoadComplete()
{
- if(mModelRoot)
+ mDiffuseTexture = (mIblDiffuseLoadTask->HasSucceeded()) ? mIblDiffuseLoadTask->GetEnvironmentMap().CreateTexture() : Texture();
+ mIblDiffuseResourceReady = true;
+ if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
{
- // Loaded model pivot is not the model center.
- mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
- mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot);
+ OnIblLoadComplete();
}
+ mIblDiffuseLoadTask.Reset();
}
-void Model::CollectRenderableActor(Actor actor)
+void Model::OnIblSpecularLoadComplete()
{
- uint32_t rendererCount = actor.GetRendererCount();
- if(rendererCount)
+ mSpecularTexture = (mIblSpecularLoadTask->HasSucceeded()) ? mIblSpecularLoadTask->GetEnvironmentMap().CreateTexture() : Texture();
+ mIblSpecularResourceReady = true;
+ if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
{
- mRenderableActors.push_back(actor);
- }
-
- uint32_t childrenCount = actor.GetChildCount();
- for(uint32_t i = 0; i < childrenCount; ++i)
- {
- CollectRenderableActor(actor.GetChildAt(i));
+ OnIblLoadComplete();
}
+ mIblSpecularLoadTask.Reset();
}
-void Model::UpdateImageBasedLightTexture()
+void Model::OnIblLoadComplete()
{
- Dali::Texture currentDiffuseTexture = (mDiffuseTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
- Dali::Texture currentSpecularTexture = (mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
- float currentIBLScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
- if(!currentDiffuseTexture || !currentSpecularTexture)
- {
- currentDiffuseTexture = mDefaultDiffuseTexture;
- currentSpecularTexture = mDefaultSpecularTexture;
- currentIBLScaleFactor = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
- }
+ UpdateImageBasedLightTexture();
- for(auto&& actor : mRenderableActors)
+ if(IsResourceReady())
{
- Actor renderableActor = actor.GetHandle();
- if(renderableActor)
- {
- uint32_t rendererCount = renderableActor.GetRendererCount();
- for(uint32_t i = 0; i < rendererCount; ++i)
- {
- Dali::Renderer renderer = renderableActor.GetRendererAt(i);
- if(renderer)
- {
- Dali::TextureSet textures = renderer.GetTextures();
- if(textures)
- {
- uint32_t textureCount = textures.GetTextureCount();
- // EnvMap requires at least 2 texture, diffuse and specular
- if(textureCount > 2u)
- {
- textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, currentDiffuseTexture);
- textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, currentSpecularTexture);
- }
- }
- }
- }
- renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIBLScaleFactor);
- }
+ Control::SetResourceReady(false);
}
}
-void Model::UpdateImageBasedLightScaleFactor()
+void Model::ResetResourceTasks()
{
- if((!mDiffuseTexture || !mSpecularTexture) &&
- (!mSceneDiffuseTexture || !mSceneSpecularTexture))
+ if(Dali::Adaptor::IsAvailable())
{
- return;
- }
-
- float currentIBLScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
- for(auto&& actor : mRenderableActors)
- {
- Actor renderableActor = actor.GetHandle();
- if(renderableActor)
+ if(mModelLoadTask)
{
- renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIBLScaleFactor);
+ Dali::AsyncTaskManager::Get().RemoveTask(mModelLoadTask);
+ mModelLoadTask.Reset();
+ }
+ if(mIblDiffuseLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
+ mIblDiffuseLoadTask.Reset();
+ }
+ if(mIblSpecularLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
+ mIblSpecularLoadTask.Reset();
}
- }
-}
-
-void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
-{
- if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
- {
- mSceneDiffuseTexture = diffuseTexture;
- mSceneSpecularTexture = specularTexture;
- mSceneIblScaleFactor = scaleFactor;
- UpdateImageBasedLightTexture();
- }
-}
-
-void Model::NotifyImageBasedLightScaleFactor(float scaleFactor)
-{
- mSceneIblScaleFactor = scaleFactor;
- if(mSceneDiffuseTexture && mSceneSpecularTexture)
- {
- UpdateImageBasedLightScaleFactor();
}
}
#include <dali/public-api/rendering/texture.h>
// INTERNAL INCLUDES
+#include <dali-scene3d/internal/common/environment-map-load-task.h>
#include <dali-scene3d/internal/common/image-based-light-observer.h>
+#include <dali-scene3d/internal/common/model-load-task.h>
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
bool IsResourceReady() const override;
/**
- * @brief Loads a model from file
- */
- void LoadModel();
-
- /**
* @brief Scales the model to fit the control or to return to original size.
*/
void ScaleModel();
void NotifyImageBasedLightScaleFactor(float scaleFactor) override;
private:
+ /**
+ * @brief Asynchronously model loading finished.
+ */
+ void OnModelLoadComplete();
+
+ /**
+ * @brief Asynchronously ibl diffusel image loading finished.
+ */
+ void OnIblDiffuseLoadComplete();
+
+ /**
+ * @brief Asynchronously ibl specular image loading finished.
+ */
+ void OnIblSpecularLoadComplete();
+
+ /**
+ * @brief Asynchronously ibl loading finished.
+ */
+ void OnIblLoadComplete();
+
+ /**
+ * @brief Reset Resource loading tasks.
+ */
+ void ResetResourceTasks();
+
+private:
std::string mModelUrl;
std::string mResourceDirectoryUrl;
Dali::Actor mModelRoot;
std::vector<WeakHandle<Actor>> mRenderableActors;
WeakHandle<Scene3D::SceneView> mParentSceneView;
+ // Asynchronous loading variable
+ ModelLoadTaskPtr mModelLoadTask;
+ EnvironmentMapLoadTaskPtr mIblDiffuseLoadTask;
+ EnvironmentMapLoadTaskPtr mIblSpecularLoadTask;
+
+ std::string mDiffuseIblUrl;
+ std::string mSpecularIblUrl;
+
// TODO: This default texture can be removed after 3D Resource Cache is added.
Dali::Texture mDefaultSpecularTexture;
Dali::Texture mDefaultDiffuseTexture;
bool mModelChildrenSensitive;
bool mModelChildrenFocusable;
bool mModelResourceReady;
- bool mIBLResourceReady;
+ bool mIblDiffuseResourceReady;
+ bool mIblSpecularResourceReady;
+ bool mIblDiffuseDirty;
+ bool mIblSpecularDirty;
};
} // namespace Internal
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
#include <dali-toolkit/public-api/image-loader/image-url.h>
#include <dali-toolkit/public-api/image-loader/image.h>
-#include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
#include <dali/devel-api/actors/camera-actor-devel.h>
#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/devel-api/common/stage.h>
#include <dali/public-api/math/math-utils.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <string_view>
// INTERNAL INCLUDES
static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity";
-Dali::Actor CreateSkybox(const std::string& skyboxUrl, Scene3D::SceneView::SkyboxType skyboxType)
+Dali::Actor CreateSkybox()
{
struct Vertex
{
skyboxGeometry.AddVertexBuffer(vertexBuffer);
skyboxGeometry.SetType(Geometry::TRIANGLES);
- Dali::Texture skyboxTexture;
- Dali::Shader shaderSkybox;
+ Dali::Shader shaderSkybox = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
Dali::Renderer skyboxRenderer;
-
- if(skyboxType == Scene3D::SceneView::SkyboxType::CUBEMAP)
- {
- skyboxTexture = Dali::Scene3D::Loader::LoadCubeMap(skyboxUrl);
- shaderSkybox = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
- }
- else // Scene3D::SceneView::SkyboxType::EQUIRECTANGULAR
- {
- // Load image from file
- PixelData pixels = Dali::Toolkit::SyncImageLoader::Load(skyboxUrl);
-
- skyboxTexture = Texture::New(TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight());
- skyboxTexture.Upload(pixels, 0, 0, 0, 0, pixels.GetWidth(), pixels.GetHeight());
- shaderSkybox = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_EQUIRECTANGULAR_SHADER_FRAG.data());
- }
-
- Dali::TextureSet skyboxTextures = TextureSet::New();
- skyboxTextures.SetTexture(0, skyboxTexture);
-
skyboxRenderer = Renderer::New(skyboxGeometry, shaderSkybox);
- skyboxRenderer.SetTextures(skyboxTextures);
skyboxRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, 2.0f);
// Enables the depth test.
skyboxRenderer.SetProperty(Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON);
{
}
-SceneView::~SceneView() = default;
+SceneView::~SceneView()
+{
+ if(Dali::Adaptor::IsAvailable())
+ {
+ if(mIblDiffuseLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
+ mIblDiffuseLoadTask.Reset();
+ }
+ if(mIblSpecularLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
+ mIblSpecularLoadTask.Reset();
+ }
+ if(mSkyboxLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
+ mSkyboxLoadTask.Reset();
+ }
+ }
+}
Dali::Scene3D::SceneView SceneView::New()
{
void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
{
- mIBLResourceReady = false;
+ bool needIblReset = false;
+ bool isOnScene = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
+ if(mDiffuseIblUrl != diffuseUrl)
+ {
+ mDiffuseIblUrl = diffuseUrl;
+ if(mDiffuseIblUrl.empty())
+ {
+ needIblReset = true;
+ }
+ else
+ {
+ mIblDiffuseDirty = true;
+ mIblDiffuseResourceReady = false;
+ }
+ }
- // If url is empty or invalid, reset IBL.
- mDiffuseTexture = (!diffuseUrl.empty()) ? Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl) : Texture();
- mSpecularTexture = (!specularUrl.empty()) ? Dali::Scene3D::Loader::LoadCubeMap(specularUrl) : Texture();
+ if(mSpecularIblUrl != specularUrl)
+ {
+ mSpecularIblUrl = specularUrl;
+ if(mSpecularIblUrl.empty())
+ {
+ needIblReset = true;
+ }
+ else
+ {
+ mIblSpecularDirty = true;
+ mIblSpecularResourceReady = false;
+ }
+ }
- mIblScaleFactor = scaleFactor;
+ // If one or both of diffuse url and specular url are empty,
+ // we don't need to request to load texture.
+ if(needIblReset)
+ {
+ if(mIblDiffuseLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
+ mIblDiffuseLoadTask.Reset();
+ }
- for(auto&& item : mItems)
+ if(mIblSpecularLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
+ mIblSpecularLoadTask.Reset();
+ }
+
+ mIblDiffuseDirty = false;
+ mIblSpecularDirty = false;
+ mIblDiffuseResourceReady = true;
+ mIblSpecularResourceReady = true;
+
+ mDiffuseTexture.Reset();
+ mSpecularTexture.Reset();
+
+ NotifyImageBasedLightTextureChange();
+ }
+ else
{
- if(item)
+ if(isOnScene && mIblDiffuseDirty)
{
- item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
+ if(mIblDiffuseLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
+ mIblDiffuseLoadTask.Reset();
+ }
+ mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, MakeCallback(this, &SceneView::OnIblDiffuseLoadComplete));
+ Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
+ mIblDiffuseDirty = false;
}
+
+ if(isOnScene && mIblSpecularDirty)
+ {
+ if(mIblSpecularLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
+ mIblSpecularLoadTask.Reset();
+ }
+ mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, MakeCallback(this, &SceneView::OnIblSpecularLoadComplete));
+ Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
+ mIblSpecularDirty = false;
+ }
+ }
+
+ if(!Dali::Equals(mIblScaleFactor, scaleFactor))
+ {
+ SetImageBasedLightScaleFactor(scaleFactor);
}
- mIBLResourceReady = true;
+ // If diffuse and specular textures are already loaded, emits resource ready signal here.
if(IsResourceReady())
{
Control::SetResourceReady(false);
void SceneView::SetSkybox(const std::string& skyboxUrl, Scene3D::SceneView::SkyboxType skyboxType)
{
- mSkyboxResourceReady = false;
- if(mSkybox)
+ mSkyboxEnvironmentMapType = skyboxType;
+ bool isOnScene = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
+ if(mSkyboxUrl != skyboxUrl)
+ {
+ mSkyboxDirty = true;
+ mSkyboxResourceReady = false;
+ mSkyboxUrl = skyboxUrl;
+ }
+
+ if(mSkyboxUrl.empty())
{
- mSkybox.Unparent();
- mSkybox.Reset();
+ if(mSkyboxLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
+ mSkyboxLoadTask.Reset();
+ }
+ if(mSkyboxImageLoader)
+ {
+ mSkyboxImageLoader.Cancel(mSkyboxImageId);
+ }
+ mSkyboxDirty = false;
+ mSkyboxResourceReady = true;
}
- mSkybox = CreateSkybox(skyboxUrl, skyboxType);
- SetSkyboxIntensity(mSkyboxIntensity);
- SetSkyboxOrientation(mSkyboxOrientation);
- if(mRootLayer)
+ else
{
- mRootLayer.Add(mSkybox);
+ if(isOnScene && mSkyboxDirty)
+ {
+ if(mSkyboxLoadTask)
+ {
+ Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
+ mSkyboxLoadTask.Reset();
+ }
+ if(mSkyboxImageLoader)
+ {
+ mSkyboxImageLoader.Cancel(mSkyboxImageId);
+ }
+ if(mSkyboxEnvironmentMapType == Scene3D::SceneView::SkyboxType::CUBEMAP)
+ {
+ mSkyboxLoadTask = new EnvironmentMapLoadTask(mSkyboxUrl, MakeCallback(this, &SceneView::OnSkyboxLoadComplete));
+ Dali::AsyncTaskManager::Get().AddTask(mSkyboxLoadTask);
+ }
+ else
+ {
+ mSkyboxImageLoader = Dali::Toolkit::AsyncImageLoader::New();
+ mSkyboxImageLoader.ImageLoadedSignal().Connect(this, &SceneView::OnSkyboxEquirectangularLoadComplete);
+ mSkyboxImageId = mSkyboxImageLoader.Load(mSkyboxUrl);
+ }
+ mSkyboxDirty = false;
+ }
}
- mSkyboxResourceReady = true;
if(IsResourceReady())
{
Control::SetResourceReady(false);
void SceneView::OnSceneConnection(int depth)
{
+ // If diffuse and specular url is not valid, IBL does not need to be loaded.
+ if(!mDiffuseIblUrl.empty() && !mSpecularIblUrl.empty())
+ {
+ SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
+ }
+
+ if(!mSkyboxUrl.empty())
+ {
+ SetSkybox(mSkyboxUrl, mSkyboxEnvironmentMapType);
+ }
+
Window window = DevelWindow::Get(Self());
if(window)
{
bool SceneView::IsResourceReady() const
{
- return mIBLResourceReady & mSkyboxResourceReady;
+ return mIblDiffuseResourceReady && mIblSpecularResourceReady && mSkyboxResourceReady;
}
void SceneView::UpdateCamera(CameraActor camera)
}
}
+void SceneView::OnSkyboxEquirectangularLoadComplete(uint32_t loadedTaskId, PixelData pixelData)
+{
+ mSkyboxTexture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+ mSkyboxTexture.Upload(pixelData, 0, 0, 0, 0, pixelData.GetWidth(), pixelData.GetHeight());
+ OnSkyboxLoadComplete();
+}
+
+void SceneView::OnSkyboxLoadComplete()
+{
+ if(!mSkybox)
+ {
+ mSkybox = CreateSkybox();
+ SetSkyboxIntensity(mSkyboxIntensity);
+ SetSkyboxOrientation(mSkyboxOrientation);
+ if(mRootLayer)
+ {
+ mRootLayer.Add(mSkybox);
+ }
+ }
+
+ mSkyboxResourceReady = true;
+ if(IsResourceReady())
+ {
+ Control::SetResourceReady(false);
+ }
+
+ Shader skyboxShader;
+ if(mSkyboxEnvironmentMapType == Scene3D::SceneView::SkyboxType::CUBEMAP)
+ {
+ mSkyboxTexture = (mSkyboxLoadTask->HasSucceeded()) ? mSkyboxLoadTask->GetEnvironmentMap().CreateTexture() : Texture();
+ skyboxShader = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
+ Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
+ mSkyboxLoadTask.Reset();
+ }
+ else
+ {
+ skyboxShader = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_EQUIRECTANGULAR_SHADER_FRAG.data());
+ }
+
+ Renderer skyboxRenderer = (mSkybox.GetRendererCount() > 0u) ? mSkybox.GetRendererAt(0u) : Renderer();
+ if(skyboxRenderer)
+ {
+ Dali::TextureSet skyboxTextures = TextureSet::New();
+ skyboxTextures.SetTexture(0, mSkyboxTexture);
+ skyboxRenderer.SetTextures(skyboxTextures);
+ skyboxRenderer.SetShader(skyboxShader);
+ }
+}
+
+void SceneView::OnIblDiffuseLoadComplete()
+{
+ mDiffuseTexture = (mIblDiffuseLoadTask->HasSucceeded()) ? mIblDiffuseLoadTask->GetEnvironmentMap().CreateTexture() : Texture();
+ mIblDiffuseResourceReady = true;
+ if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
+ {
+ OnIblLoadComplete();
+ }
+ mIblDiffuseLoadTask.Reset();
+}
+
+void SceneView::OnIblSpecularLoadComplete()
+{
+ mSpecularTexture = (mIblSpecularLoadTask->HasSucceeded()) ? mIblSpecularLoadTask->GetEnvironmentMap().CreateTexture() : Texture();
+ mIblSpecularResourceReady = true;
+ if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
+ {
+ OnIblLoadComplete();
+ }
+ mIblSpecularLoadTask.Reset();
+}
+
+void SceneView::OnIblLoadComplete()
+{
+ NotifyImageBasedLightTextureChange();
+ if(IsResourceReady())
+ {
+ Control::SetResourceReady(false);
+ }
+}
+
+void SceneView::NotifyImageBasedLightTextureChange()
+{
+ for(auto&& item : mItems)
+ {
+ if(item)
+ {
+ item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
+ }
+ }
+}
+
} // namespace Internal
} // namespace Scene3D
} // namespace Dali
// EXTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/image/image-visual.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/image-loader/async-image-loader.h>
#include <dali/public-api/actors/camera-actor.h>
#include <dali/public-api/actors/layer.h>
#include <dali/public-api/adaptor-framework/window.h>
#include <dali/public-api/rendering/texture.h>
// INTERNAL INCLUDES
-#include <dali-scene3d/internal/common/image-based-light-observer.h>
#include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
+#include <dali-scene3d/internal/common/environment-map-load-task.h>
+#include <dali-scene3d/internal/common/image-based-light-observer.h>
namespace Dali
{
*/
void RotateCamera();
+ /**
+ * @brief Asynchronously skybox (Equirectangular) loading finished.
+ */
+ void OnSkyboxEquirectangularLoadComplete(uint32_t loadedTaskId, PixelData pixelData);
+
+ /**
+ * @brief Asynchronously skybox loading finished.
+ */
+ void OnSkyboxLoadComplete();
+
+ /**
+ * @brief Asynchronously ibl diffusel image loading finished.
+ */
+ void OnIblDiffuseLoadComplete();
+
+ /**
+ * @brief Asynchronously ibl specular image loading finished.
+ */
+ void OnIblSpecularLoadComplete();
+
+ /**
+ * @brief Asynchronously ibl loading finished.
+ */
+ void OnIblLoadComplete();
+
+ /**
+ * @brief Notify the changes of Ibl textures to the child items.
+ */
+ void NotifyImageBasedLightTextureChange();
+
private:
Toolkit::Visual::Base mVisual;
Quaternion mSkyboxOrientation;
float mSkyboxIntensity{1.0f};
- Dali::Texture mSpecularTexture;
- Dali::Texture mDiffuseTexture;
- float mIblScaleFactor{1.0f};
- bool mUseFrameBuffer{false};
- bool mIBLResourceReady{true};
- bool mSkyboxResourceReady{true};
+ // Asynchronous Loading.
+ EnvironmentMapLoadTaskPtr mSkyboxLoadTask;
+ EnvironmentMapLoadTaskPtr mIblDiffuseLoadTask;
+ EnvironmentMapLoadTaskPtr mIblSpecularLoadTask;
+ std::string mSkyboxUrl;
+ std::string mDiffuseIblUrl;
+ std::string mSpecularIblUrl;
+ Dali::Toolkit::AsyncImageLoader mSkyboxImageLoader;
+ uint32_t mSkyboxImageId{0u};
+
+ Scene3D::SceneView::SkyboxType mSkyboxEnvironmentMapType;
+ Dali::Texture mSkyboxTexture;
+ Dali::Texture mDiffuseTexture;
+ Dali::Texture mSpecularTexture;
+ float mIblScaleFactor{1.0f};
+ bool mUseFrameBuffer{false};
+ bool mSkyboxResourceReady{true};
+ bool mIblDiffuseResourceReady{true};
+ bool mIblSpecularResourceReady{true};
+ bool mSkyboxDirty{false};
+ bool mIblDiffuseDirty{false};
+ bool mIblSpecularDirty{false};
// TODO : Light Source
};
set(scene3d_internal_dir "${scene3d_dir}/internal")
set(scene3d_src_files ${scene3d_src_files}
+ ${scene3d_internal_dir}/common/environment-map-load-task.cpp
+ ${scene3d_internal_dir}/common/model-load-task.cpp
${scene3d_internal_dir}/controls/model/model-impl.cpp
${scene3d_internal_dir}/controls/scene-view/scene-view-impl.cpp
${scene3d_internal_dir}/loader/gltf2-asset.cpp
*
* @SINCE_2_2.0
* @param[in] skyboxUrl image url for skybox.
- * @param[in] skyboxType The skybox type (by default it is cubemap).
+ * @param[in] skyboxType The environment type of skymap (by default it is cubemap).
*/
void SetSkybox(const std::string& skyboxUrl, SkyboxType skyboxType = SkyboxType::CUBEMAP);
void AnimationDefinition::Animate(Animation& animation, AnimatedProperty::GetActor getActor)
{
DALI_ASSERT_ALWAYS(animation);
- for(auto& ap : mProperties)
+ for(auto& property : mProperties)
{
- ap.Animate(animation, getActor);
+ property.Animate(animation, getActor);
}
}
Animation AnimationDefinition::ReAnimate(AnimatedProperty::GetActor getActor)
{
// Create and configure new animation.
- Animation a = Animation::New(mDuration);
- a.SetLoopCount(mLoopCount);
- a.SetDisconnectAction(mDisconnectAction);
- a.SetEndAction(mEndAction);
+ Animation animation = Animation::New(mDuration);
+ animation.SetLoopCount(mLoopCount);
+ animation.SetDisconnectAction(mDisconnectAction);
+ animation.SetEndAction(mEndAction);
- a.SetSpeedFactor(mSpeedFactor);
- a.SetPlayRange(mPlayRange);
+ animation.SetSpeedFactor(mSpeedFactor);
+ animation.SetPlayRange(mPlayRange);
- Animate(a, getActor);
- return a;
+ Animate(animation, getActor);
+ return animation;
}
AnimationDefinition& AnimationDefinition::operator=(AnimationDefinition&& other)
{
bool LoadCubeData(const std::string& path, CubeData& cubedata)
{
- Texture cubeTexture;
// Diffuse Cube Map
if(path.empty())
{
face.push_back(PixelData::New(new uint8_t[3]{0xff, 0xff, 0xff}, 3, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY));
}
}
- else if(!LoadCubeMapData(environmentsPath + path, cd))
+ else if(!LoadCubeMapData(environmentsPath + path, cd)) // TODO: supporting EQUIRECTANGULAR
{
ExceptionFlinger(ASSERT_LOCATION) << "Failed to load cubemap texture from '" << path << "'.";
}
// EXTERNAL INCLUDES
#include "dali/public-api/math/quaternion.h"
#include "dali/public-api/rendering/texture.h"
+#include <memory>
namespace Dali
{
static float GetDefaultIntensity();
public: // DATA
- std::string mDiffuseMapPath;
- std::string mSpecularMapPath;
- Quaternion mCubeOrientation = Quaternion::IDENTITY;
- Vector3 mYDirection = Vector3::ONE;
- float mIblIntensity = 1.0f;
- bool mUseBrdfTexture = false;
+ std::string mDiffuseMapPath;
+ std::string mSpecularMapPath;
+ std::shared_ptr<RawData> mRawData;
+ Quaternion mCubeOrientation = Quaternion::IDENTITY;
+ Vector3 mYDirection = Vector3::ONE;
+ float mIblIntensity = 1.0f;
+ bool mUseBrdfTexture = false;
};
} // namespace Loader
#include <dali/integration-api/debug.h>
#include <dali/public-api/images/image-operations.h>
#include <dali/public-api/math/quaternion.h>
+#include <dali/devel-api/threading/mutex.h>
#include <fstream>
// INTERNAL INCLUDES
{
namespace
{
+Dali::Mutex gInitializeMutex;
+Dali::Mutex gReadMutex;
+
const std::string POSITION_PROPERTY("position");
const std::string ORIENTATION_PROPERTY("orientation");
const std::string SCALE_PROPERTY("scale");
std::vector<gt::Animation> ReadAnimationArray(const json_value_s& j)
{
- gt::Animation proxy;
- SetRefReaderObject(proxy);
-
auto results = js::Read::Array<gt::Animation, js::ObjectReader<gt::Animation>::Read>(j);
for(auto& animation : results)
} // namespace
+void InitializeGltfLoader()
+{
+ // Set ObjectReader only once (for all gltf loading).
+ static bool setObjectReadersRequired = true;
+ {
+ Mutex::ScopedLock lock(gInitializeMutex);
+ if(setObjectReadersRequired)
+ {
+ // NOTE: only referencing own, anonymous namespace, const objects; the pointers will never need to change.
+ SetObjectReaders();
+ setObjectReadersRequired = false;
+ }
+ }
+}
+
void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactory, LoadResult& params)
{
bool failed = false;
throw std::runtime_error("Failed to parse " + url);
}
- static bool setObjectReaders = true;
- if(setObjectReaders)
- {
- // NOTE: only referencing own, anonymous namespace, const objects; the pointers will never need to change.
- SetObjectReaders();
- setObjectReaders = false;
- }
-
gt::Document doc;
auto& rootObj = js::Cast<json_object_s>(*root);
isMRendererModel = (doc.mAsset.mGenerator.find(MRENDERER_MODEL_IDENTIFICATION) != std::string_view::npos);
}
- gt::SetRefReaderObject(doc);
- DOCUMENT_READER.Read(rootObj, doc);
+ {
+ Mutex::ScopedLock lock(gReadMutex);
+ gt::SetRefReaderObject(doc);
+ DOCUMENT_READER.Read(rootObj, doc);
+ }
auto path = url.substr(0, url.rfind('/') + 1);
ConversionContext context{params, path, INVALID_INDEX};
class ShaderDefinitionFactory;
/**
+ * @brief Initialize glTF Loader.
+ * @note This method should be called once before LoadGltfScene() is called.
+ */
+DALI_SCENE3D_API void InitializeGltfLoader();
+
+/**
* @brief Loads the scene from the glTF file located at @a url, storing the results in @a params.
* @note Will throw std::runtime_error for JSON entities with types mismatching expectations, carrying
* invalid values, or I/O errors.
+ * @note InitializeGltfLoader() should be called once before this function is called.
*/
DALI_SCENE3D_API void LoadGltfScene(const std::string& url, ShaderDefinitionFactory& shaderFactory, LoadResult& params);
}
public: // DATA
- uint32_t mFlags = 0x0;
+ std::shared_ptr<RawData> mRawData;
+ uint32_t mFlags = 0x0;
Index mEnvironmentIdx = 0;
Vector4 mColor = Color::WHITE;
MeshGeometry Load(RawData&& raw) const;
public: // DATA
- uint32_t mFlags = 0x0;
- Geometry::Type mPrimitiveType = Geometry::TRIANGLES;
- std::string mUri;
- Accessor mIndices;
- Accessor mPositions;
- Accessor mNormals; // data can be generated based on positions
- Accessor mTexCoords;
- Accessor mColors;
- Accessor mTangents; // data can be generated based on normals and texCoords (the latter isn't mandatory; the results will be better if available)
- Accessor mJoints0;
- Accessor mWeights0;
- Property::Type mTangentType{Property::VECTOR3};
+ std::shared_ptr<RawData> mRawData;
+ uint32_t mFlags = 0x0;
+ Geometry::Type mPrimitiveType = Geometry::TRIANGLES;
+ std::string mUri;
+ Accessor mIndices;
+ Accessor mPositions;
+ Accessor mNormals; // data can be generated based on positions
+ Accessor mTexCoords;
+ Accessor mColors;
+ Accessor mTangents; // data can be generated based on normals and texCoords (the latter isn't mandatory; the results will be better if available)
+ Accessor mJoints0;
+ Accessor mWeights0;
+ Property::Type mTangentType{Property::VECTOR3};
Blob mBlendShapeHeader;
std::vector<BlendShape> mBlendShapes;
}
}
+void ResourceBundle::LoadRawResources(const ResourceRefCounts& refCounts, PathProvider pathProvider, Options::Type options)
+{
+ const auto kForceLoad = MaskMatch(options, Options::ForceReload);
+
+ const auto& refCountEnvMaps = refCounts[ResourceType::Environment];
+ auto environmentsPath = pathProvider(ResourceType::Environment);
+ for(uint32_t i = 0, iEnd = refCountEnvMaps.Size(); i != iEnd; ++i)
+ {
+ auto refCount = refCountEnvMaps[i];
+ auto& iEnvMap = mEnvironmentMaps[i];
+ if(refCount > 0 && (kForceLoad || !iEnvMap.second.IsLoaded()))
+ {
+ iEnvMap.first.mRawData = std::make_shared<EnvironmentDefinition::RawData>(iEnvMap.first.LoadRaw(environmentsPath));
+ }
+ }
+
+ const auto& refCountShaders = refCounts[ResourceType::Shader];
+ auto shadersPath = pathProvider(ResourceType::Shader);
+ for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i)
+ {
+ auto refCount = refCountShaders[i];
+ auto& iShader = mShaders[i];
+ if(refCount > 0 && (kForceLoad || !iShader.second))
+ {
+ iShader.first.mRawData = std::make_shared<ShaderDefinition::RawData>(iShader.first.LoadRaw(shadersPath));
+ }
+ }
+
+ const auto& refCountMeshes = refCounts[ResourceType::Mesh];
+ auto modelsPath = pathProvider(ResourceType::Mesh);
+ for(uint32_t i = 0, iEnd = refCountMeshes.Size(); i != iEnd; ++i)
+ {
+ auto refCount = refCountMeshes[i];
+ auto& iMesh = mMeshes[i];
+ if(refCount > 0 && (kForceLoad || !iMesh.second.geometry))
+ {
+ iMesh.first.mRawData = std::make_shared<MeshDefinition::RawData>(iMesh.first.LoadRaw(modelsPath));
+ }
+ }
+
+ const auto& refCountMaterials = refCounts[ResourceType::Material];
+ auto imagesPath = pathProvider(ResourceType::Material);
+ for(uint32_t i = 0, iEnd = refCountMaterials.Size(); i != iEnd; ++i)
+ {
+ auto refCount = refCountMaterials[i];
+ auto& iMaterial = mMaterials[i];
+ if(refCount > 0 && (kForceLoad || !iMaterial.second))
+ {
+ iMaterial.first.mRawData = std::make_shared<MaterialDefinition::RawData>(iMaterial.first.LoadRaw(imagesPath));
+ }
+ }
+}
+
+void ResourceBundle::GenerateResources(const ResourceRefCounts& refCounts, Options::Type options)
+{
+ const auto& refCountEnvMaps = refCounts[ResourceType::Environment];
+ for(uint32_t i = 0, iEnd = refCountEnvMaps.Size(); i != iEnd; ++i)
+ {
+ auto& iEnvMap = mEnvironmentMaps[i];
+ if(iEnvMap.first.mRawData)
+ {
+ iEnvMap.second = iEnvMap.first.Load(std::move(*(iEnvMap.first.mRawData)));
+ }
+ else
+ {
+ iEnvMap.second.mDiffuse = Texture();
+ iEnvMap.second.mSpecular = Texture();
+ }
+ }
+
+ const auto& refCountShaders = refCounts[ResourceType::Shader];
+ for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i)
+ {
+ auto& iShader = mShaders[i];
+ if(iShader.first.mRawData)
+ {
+ iShader.second = iShader.first.Load(std::move(*(iShader.first.mRawData)));
+ }
+ else
+ {
+ iShader.second = Shader();
+ }
+ }
+
+ const auto& refCountMeshes = refCounts[ResourceType::Mesh];
+ for(uint32_t i = 0, iEnd = refCountMeshes.Size(); i != iEnd; ++i)
+ {
+ auto& iMesh = mMeshes[i];
+ if(iMesh.first.mRawData)
+ {
+ iMesh.second = iMesh.first.Load(std::move(*(iMesh.first.mRawData)));
+ }
+ else
+ {
+ iMesh.second.geometry = Geometry();
+ }
+ }
+
+ const auto& refCountMaterials = refCounts[ResourceType::Material];
+ for(uint32_t i = 0, iEnd = refCountMaterials.Size(); i != iEnd; ++i)
+ {
+ auto& iMaterial = mMaterials[i];
+ if(iMaterial.first.mRawData)
+ {
+ iMaterial.second = iMaterial.first.Load(mEnvironmentMaps, std::move(*(iMaterial.first.mRawData)));
+ }
+ else
+ {
+ iMaterial.second = TextureSet();
+ }
+ }
+}
+
} // namespace Loader
} // namespace Scene3D
} // namespace Dali
ResourceBundle(ResourceBundle&&) = default;
ResourceBundle& operator=(ResourceBundle&&) = default;
- /*
+ /**
* @return A ResourceRefCounts object with the correct number of entries for
* all resource types (based on the various resource definition vectors),
* with all reference counts set to 0.
*/
ResourceRefCounts CreateRefCounter() const;
- /*
+ /**
* @brief Based on a ResourceRefCounts, and more specifically the reference
* count of materials therein, it will calculate the reference count of
* environment maps.
*/
void CountEnvironmentReferences(ResourceRefCounts& refCounts) const;
- /*
+ /**
* @brief Performs the loading of all resources based on their respective
- * reference count in @a refCounts. Resources that had a non-zero ref count will be
- * loaded unless we already have a handle to them (OR the ForceReload option was specified).
- * Any handles we have to resources that come in with a zero ref count will be reset,
- * UNLESS the KeepUnused option was specified.
+ * reference count in @a refCounts. Resources that had a non-zero ref count will be
+ * loaded unless we already have a handle to them (OR the ForceReload option was specified).
+ * Any handles we have to resources that come in with a zero ref count will be reset,
+ * UNLESS the KeepUnused option was specified.
+ * @param[in] refCounts Reference Count that denote how many the resource is used.
+ * @param[in] pathProvider path provider for resource data.
+ * @param[in] options Option to load resource
+ * @note This method creates DALi objects like Dali::Texture, Dali::Geometry, etc.
*/
void LoadResources(const ResourceRefCounts& refCounts,
PathProvider pathProvider,
Options::Type options = Options::None);
+ /**
+ * @brief Loads of all resources based on their respective
+ * reference count in @a refCounts. Resources that had a non-zero ref count will be
+ * loaded unless we already have a handle to them (OR the ForceReload option was specified).
+ * Any handles we have to resources that come in with a zero ref count will be reset,
+ * UNLESS the KeepUnused option was specified.
+ * @note This method don't create any of DALi objects.
+ * @param[in] refCounts Reference Count that denote how many the resource is used.
+ * @param[in] pathProvider path provider for resource data.
+ * @param[in] options Option to load resource
+ * @note This method only loads raw data from resource file, and
+ * doesn't create any of DALi objects. GenerateResources() method is required to be called
+ * after this method to create DALi objects.
+ */
+ void LoadRawResources(const ResourceRefCounts& refCounts,
+ PathProvider pathProvider,
+ Options::Type options = Options::None);
+
+ /**
+ * @brief Generates DALi objects from already loaded Raw Resources.
+ * @param[in] refCounts Reference Count that denote how many the resource is used.
+ * @param[in] options Option to load resource
+ * @note This method generates DALi objects from raw data that is already
+ * loaded by LoadRawResources method. Therefore, LoadRawResources should be called first
+ * before this method is called.
+ */
+ void GenerateResources(const ResourceRefCounts& refCounts,
+ Options::Type options = Options::None);
+
public: // DATA
EnvironmentDefinition::Vector mEnvironmentMaps;
ShaderDefinition::Vector mShaders;
ShaderDefinition(const ShaderDefinition& other);
ShaderDefinition& operator=(const ShaderDefinition& other);
- ShaderDefinition(ShaderDefinition&&) = default;
+ ShaderDefinition(ShaderDefinition&&) = default;
ShaderDefinition& operator=(ShaderDefinition&&) = default;
/*
Shader Load(RawData&& raw) const;
public: // DATA
- RendererState::Type mRendererState = RendererState::NONE;
+ std::shared_ptr<RawData> mRawData;
+ RendererState::Type mRendererState = RendererState::NONE;
std::string mVertexShaderPath;
std::string mFragmentShaderPath;
} // namespace Scene3D
} // namespace Dali
-#endif //DALI_SCENE3D_LOADER_SHADER_DEFINITION_H
+#endif // DALI_SCENE3D_LOADER_SHADER_DEFINITION_H