{
+ "extensionsUsed" : [
+ "KHR_materials_specular",
+ "KHR_materials_ior"
+ ],
+
"accessors" : [
{
"bufferView" : 0,
],
"materials" : [
{
+ "extensions" : {
+ "KHR_materials_specular" : {
+ "specularColorFactor" : [
+ 0,
+ 0,
+ 1
+ ],
+ "specularFactor" : 0.5,
+ "specularTexture": {
+ "index": 0
+ },
+ "specularColorTexture": {
+ "index": 0
+ }
+ },
+ "KHR_materials_ior" : {
+ "ior" : 1.0
+ }
+ },
"name" : "AnimatedCube",
"pbrMetallicRoughness" : {
"baseColorTexture" : {
--- /dev/null
+{\r
+ "scene" : 0,\r
+ "scenes" : [\r
+ {\r
+ "nodes" : [ 0 ]\r
+ }\r
+ ],\r
+\r
+ "nodes" : [\r
+ {\r
+ "name" : "rootNode",\r
+ "mesh" : 0,\r
+ "rotation" : [ 0.0, 0.0, 0.0, 1.0 ]\r
+ }\r
+ ],\r
+\r
+ "meshes" : [\r
+ {\r
+ "primitives" : [\r
+ {\r
+ "attributes" : {\r
+ "POSITION" : 1\r
+ },\r
+ "indices" : 0\r
+ },\r
+ {\r
+ "attributes" : {\r
+ "POSITION" : 1\r
+ },\r
+ "indices" : 0\r
+ }\r
+ ]\r
+ }\r
+ ],\r
+\r
+ "buffers" : [\r
+ {\r
+ "uri" : "simpleTriangle.bin",\r
+ "byteLength" : 44\r
+ },\r
+ {\r
+ "uri" : "animation.bin",\r
+ "byteLength" : 100\r
+ }\r
+ ],\r
+\r
+ "bufferViews" : [\r
+ {\r
+ "buffer" : 0,\r
+ "byteOffset" : 0,\r
+ "byteLength" : 6,\r
+ "target" : 34963\r
+ },\r
+ {\r
+ "buffer" : 0,\r
+ "byteOffset" : 8,\r
+ "byteLength" : 36,\r
+ "target" : 34962\r
+ },\r
+ {\r
+ "buffer" : 1,\r
+ "byteOffset" : 0,\r
+ "byteLength" : 100\r
+ }\r
+ ],\r
+\r
+ "accessors" : [\r
+ {\r
+ "bufferView" : 0,\r
+ "byteOffset" : 0,\r
+ "componentType" : 5123,\r
+ "count" : 3,\r
+ "type" : "SCALAR",\r
+ "max" : [ 2 ],\r
+ "min" : [ 0 ]\r
+ },\r
+ {\r
+ "bufferView" : 1,\r
+ "byteOffset" : 0,\r
+ "componentType" : 5126,\r
+ "count" : 3,\r
+ "type" : "VEC3",\r
+ "max" : [ 1.0, 1.0, 0.0 ],\r
+ "min" : [ 0.0, 0.0, 0.0 ]\r
+ },\r
+ {\r
+ "bufferView" : 2,\r
+ "byteOffset" : 0,\r
+ "componentType" : 5126,\r
+ "count" : 5,\r
+ "type" : "SCALAR",\r
+ "max" : [ 1.0 ],\r
+ "min" : [ 0.0 ]\r
+ },\r
+ {\r
+ "bufferView" : 2,\r
+ "byteOffset" : 20,\r
+ "componentType" : 5126,\r
+ "count" : 5,\r
+ "type" : "VEC4",\r
+ "max" : [ 0.0, 0.0, 1.0, 1.0 ],\r
+ "min" : [ 0.0, 0.0, 0.0, -0.707 ]\r
+ }\r
+ ],\r
+\r
+ "asset" : {\r
+ "version" : "2.0"\r
+ }\r
+}\r
DALI_TEST_EQUAL(2u, materials.size());
const MaterialDefinition materialGroundTruth[]{
{MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
- MaterialDefinition::NORMAL | MaterialDefinition::TRANSPARENCY |
+ MaterialDefinition::NORMAL | MaterialDefinition::SPECULAR | MaterialDefinition::SPECULAR_COLOR |
(0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
0,
Color::WHITE,
1.f,
1.f,
Vector3(0.2, 0.1, 0.0),
+ 0.0f,
+ 0.5f,
+ Vector3(0, 0, 1),
true,
false,
true,
+ false,
{
{MaterialDefinition::ALBEDO,
{"AnimatedCube_BaseColor.png",
{MaterialDefinition::EMISSIVE,
{"AnimatedCube_BaseColor.png",
SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+ {MaterialDefinition::SPECULAR,
+ {"AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+ {MaterialDefinition::SPECULAR_COLOR,
+ {"AnimatedCube_BaseColor.png",
+ SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
}},
{MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
1.f,
1.f,
Vector3(0.2, 0.1, 0.0),
+ 0.04f,
+ 1.0f,
+ Vector3::ONE,
true,
true,
true,
+ false,
{
{MaterialDefinition::ALBEDO,
{"AnimatedCube_BaseColor.png",
DALI_TEST_EQUAL(md.mNormalScale, m.mNormalScale);
DALI_TEST_EQUAL(md.mOcclusionStrength, m.mOcclusionStrength);
DALI_TEST_EQUAL(md.mEmissiveFactor, m.mEmissiveFactor);
+ DALI_TEST_EQUAL(md.mDielectricSpecular, m.mDielectricSpecular);
+ DALI_TEST_EQUAL(md.mSpecularFactor, m.mSpecularFactor);
+ DALI_TEST_EQUAL(md.mSpecularColorFactor, m.mSpecularColorFactor);
DALI_TEST_EQUAL(md.mNeedAlbedoTexture, m.mNeedAlbedoTexture);
DALI_TEST_EQUAL(md.mNeedMetallicRoughnessTexture, m.mNeedMetallicRoughnessTexture);
DALI_TEST_EQUAL(md.mNeedNormalTexture, m.mNeedNormalTexture);
void Start(NodeDefinition& n) override
{
- if(n.mRenderable)
+ for(auto& renderable : n.mRenderables)
{
- n.mRenderable->RegisterResources(receiver);
+ renderable->RegisterResources(receiver);
}
}
* Donated by Norbert Nopper for glTF testing.
* Take from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnimatedCube
*/
-const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf";
-const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME = TEST_RESOURCE_DIR "/animationTest.gltf";
-const char* TEST_DLI_FILE_NAME = TEST_RESOURCE_DIR "/arc.dli";
+const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf";
+const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME = TEST_RESOURCE_DIR "/animationTest.gltf";
+const char* TEST_GLTF_MULTIPLE_PRIMITIVE_FILE_NAME = TEST_RESOURCE_DIR "/simpleMultiplePrimitiveTest.gltf";
+const char* TEST_DLI_FILE_NAME = TEST_RESOURCE_DIR "/arc.dli";
/**
* For the diffuse and specular cube map texture.
* These textures are based off version of Wave engine sample
DALI_TEST_CHECK(renderer);
TextureSet textureSet = renderer.GetTextures();
- DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+ DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION);
- Texture diffuseTexture = textureSet.GetTexture(5u);
- Texture specularTexture = textureSet.GetTexture(6u);
+ Texture diffuseTexture = textureSet.GetTexture(7u);
+ Texture specularTexture = textureSet.GetTexture(8u);
model.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
- Texture newDiffuseTexture = textureSet.GetTexture(5u);
- Texture newSpecularTexture = textureSet.GetTexture(6u);
+ 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);
DALI_TEST_CHECK(renderer);
TextureSet textureSet = renderer.GetTextures();
- DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+ DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION);
- Texture diffuseTexture = textureSet.GetTexture(5u);
- Texture specularTexture = textureSet.GetTexture(6u);
+ Texture diffuseTexture = textureSet.GetTexture(7u);
+ Texture specularTexture = textureSet.GetTexture(8u);
model.SetImageBasedLightSource("", "");
- Texture newDiffuseTexture = textureSet.GetTexture(5u);
- Texture newSpecularTexture = textureSet.GetTexture(6u);
+ Texture newDiffuseTexture = textureSet.GetTexture(7u);
+ Texture newSpecularTexture = textureSet.GetTexture(8u);
DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION);
DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION);
DALI_TEST_CHECK(renderer);
TextureSet textureSet = renderer.GetTextures();
- DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+ DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION);
- Texture diffuseTexture = textureSet.GetTexture(5u);
- Texture specularTexture = textureSet.GetTexture(6u);
+ Texture diffuseTexture = textureSet.GetTexture(7u);
+ Texture specularTexture = textureSet.GetTexture(8u);
model.SetImageBasedLightSource("dummy.ktx", "dummy.ktx");
- Texture newDiffuseTexture = textureSet.GetTexture(5u);
- Texture newSpecularTexture = textureSet.GetTexture(6u);
+ Texture newDiffuseTexture = textureSet.GetTexture(7u);
+ Texture newSpecularTexture = textureSet.GetTexture(8u);
DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION);
DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION);
END_TEST;
}
+int UtcDaliModelMultiplePrimitives(void)
+{
+ ToolkitTestApplication application;
+
+ 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);
+
+ application.SendNotification();
+ application.Render();
+
+ Actor actor = model.FindChildByName("rootNode");
+
+ DALI_TEST_EQUALS(0, actor.GetChildCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(2, actor.GetRendererCount(), TEST_LOCATION);
+
+ END_TEST;
+}
+
// For ResourceReady
namespace
{
// Enable debug log for test coverage
#define DEBUG_ENABLED 1
-#include "dali-scene3d/public-api/loader/node-definition.h"
-#include "dali-scene3d/public-api/loader/view-projection.h"
-#include <toolkit-test-application.h>
#include <dali-test-suite-utils.h>
+#include <toolkit-test-application.h>
#include <string_view>
+#include "dali-scene3d/public-api/loader/node-definition.h"
+#include "dali-scene3d/public-api/loader/view-projection.h"
using namespace Dali;
using namespace Dali::Scene3D::Loader;
ResourceBundle resources;
ViewProjection viewProjection;
- Transforms transforms { MatrixStack{}, viewProjection };
+ Transforms transforms{MatrixStack{}, viewProjection};
- NodeDefinition::CreateParams createParams {
+ NodeDefinition::CreateParams createParams{
resources,
- transforms
- };
+ transforms};
};
-}
+} // namespace
int UtcDaliConstraintDefinitionsCompare(void)
{
- ConstraintDefinition cd1{ "orientation", 0 };
- ConstraintDefinition cd2{ "position", 1 };
+ ConstraintDefinition cd1{"orientation", 0};
+ ConstraintDefinition cd2{"position", 1};
DALI_TEST_CHECK(cd1 < cd2);
DALI_TEST_CHECK(!(cd2 < cd1));
DALI_TEST_CHECK(cd1 == cd1);
DALI_TEST_CHECK(cd2 == cd2);
- ConstraintDefinition cd3{ "position", 0 };
- ConstraintDefinition cd4{ "scale", 1 };
- ConstraintDefinition cd5{ "position", 1 };
+ ConstraintDefinition cd3{"position", 0};
+ ConstraintDefinition cd4{"scale", 1};
+ ConstraintDefinition cd5{"position", 1};
DALI_TEST_CHECK(cd2 != cd3);
DALI_TEST_CHECK(cd2 != cd4);
DALI_TEST_CHECK(cd2 == cd5);
int UtcDaliBlendshapeShaderConfigurationRequestsCompare(void)
{
- TestApplication app;
- BlendshapeShaderConfigurationRequest bsscr1{ "", 0, Shader(nullptr) };
+ TestApplication app;
+ BlendshapeShaderConfigurationRequest bsscr1{"", 0, Shader(nullptr)};
- BlendshapeShaderConfigurationRequest bsscr2{ "", 0, Shader::New(
- "void main(){ gl_Position = vec4(0.); }",
- "void main(){ gl_FragColor = vec4(1.); }"
- ) };
+ BlendshapeShaderConfigurationRequest bsscr2{"", 0, Shader::New("void main(){ gl_Position = vec4(0.); }", "void main(){ gl_FragColor = vec4(1.); }")};
DALI_TEST_CHECK(bsscr1 < bsscr2);
DALI_TEST_CHECK(!(bsscr2 < bsscr1));
int UtcDaliNodeDefinitionExtrasCompare(void)
{
- NodeDefinition::Extra e1{ "alpha", Vector3::XAXIS * 2.f };
- NodeDefinition::Extra e2{ "beta", 8 };
+ NodeDefinition::Extra e1{"alpha", Vector3::XAXIS * 2.f};
+ NodeDefinition::Extra e2{"beta", 8};
DALI_TEST_CHECK(e1 < e2);
DALI_TEST_CHECK(!(e1 < e1));
int UtcDaliNodeDefinitionProperties(void)
{
TestApplication testApp;
- NodeDefinition nodeDef{
+ NodeDefinition nodeDef{
"testRootNode",
- Vector3{ -100.f, 100.f, -500.f },
- Quaternion{ Radian(Degree(45.f)), Vector3::ZAXIS },
- Vector3{ 2.f, 4.f, 8.f },
- Vector3{ 100.f, 50.f, 25.f },
+ Vector3{-100.f, 100.f, -500.f},
+ Quaternion{Radian(Degree(45.f)), Vector3::ZAXIS},
+ Vector3{2.f, 4.f, 8.f},
+ Vector3{100.f, 50.f, 25.f},
false,
};
Quaternion frobnicateFactor(0.f, 1.f, 2.f, 3.f);
frobnicateFactor.Normalize(); // because it will be (by DALi) once it's set as a property.
- nodeDef.mExtras.push_back(NodeDefinition::Extra{ "frobnicateFactor", frobnicateFactor });
+ nodeDef.mExtras.push_back(NodeDefinition::Extra{"frobnicateFactor", frobnicateFactor});
Context ctx;
- auto actor = nodeDef.CreateActor(ctx.createParams);
+ auto actor = nodeDef.CreateActor(ctx.createParams);
DALI_TEST_EQUAL(nodeDef.mName, actor.GetProperty(Actor::Property::NAME).Get<std::string>());
DALI_TEST_EQUAL(nodeDef.mPosition, actor.GetProperty(Actor::Property::POSITION).Get<Vector3>());
DALI_TEST_EQUAL(nodeDef.mOrientation, actor.GetProperty(Actor::Property::ORIENTATION).Get<Quaternion>());
{
NodeDefinition nodeDef;
- auto renderable = new NodeDefinition::Renderable();
- renderable->mShaderIdx = 0;
- nodeDef.mRenderable.reset(renderable);
+ std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(new NodeDefinition::Renderable());
+ nodeDef.mRenderables.push_back(std::move(renderable));
+ nodeDef.mRenderables[0]->mShaderIdx = 0;
struct : IResourceReceiver
{
std::vector<Index> shaders;
- uint32_t otherResources = 0;
+ uint32_t otherResources = 0;
void Register(ResourceType::Value type, Index id) override
{
switch(type)
{
- case ResourceType::Shader:
- shaders.push_back(id);
- break;
+ case ResourceType::Shader:
+ shaders.push_back(id);
+ break;
- default:
- ++otherResources;
+ default:
+ ++otherResources;
}
}
} resourceReceiver;
- nodeDef.mRenderable->RegisterResources(resourceReceiver);
+ nodeDef.mRenderables[0]->RegisterResources(resourceReceiver);
DALI_TEST_EQUAL(1u, resourceReceiver.shaders.size());
DALI_TEST_EQUAL(0, resourceReceiver.shaders[0]);
DALI_TEST_EQUAL(0, resourceReceiver.otherResources);
{
NodeDefinition nodeDef;
- auto renderable = new NodeDefinition::Renderable();
- renderable->mShaderIdx = 0;
- nodeDef.mRenderable.reset(renderable);
+ std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(new NodeDefinition::Renderable());
+ nodeDef.mRenderables.push_back(std::move(renderable));
+ nodeDef.mRenderables[0]->mShaderIdx = 0;
struct : IResourceReflector
{
std::vector<Index*> shaders;
- uint32_t otherResources = 0;
+ uint32_t otherResources = 0;
void Reflect(ResourceType::Value type, Index& id) override
{
switch(type)
{
- case ResourceType::Shader:
- shaders.push_back(&id);
- break;
+ case ResourceType::Shader:
+ shaders.push_back(&id);
+ break;
- default:
- ++otherResources;
+ default:
+ ++otherResources;
}
}
} resourceReflector;
- nodeDef.mRenderable->ReflectResources(resourceReflector);
+ nodeDef.mRenderables[0]->ReflectResources(resourceReflector);
DALI_TEST_EQUAL(1u, resourceReflector.shaders.size());
- DALI_TEST_EQUAL(&renderable->mShaderIdx, resourceReflector.shaders[0]);
+ DALI_TEST_EQUAL(&nodeDef.mRenderables[0]->mShaderIdx, resourceReflector.shaders[0]);
DALI_TEST_EQUAL(0, resourceReflector.otherResources);
END_TEST;
int UtcDaliNodeDefinitionRenderable(void)
{
TestApplication testApp;
- NodeDefinition nodeDef;
+ NodeDefinition nodeDef;
- auto renderable = new NodeDefinition::Renderable();
- renderable->mShaderIdx = 0;
- nodeDef.mRenderable.reset(renderable);
+ std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(new NodeDefinition::Renderable());
+ nodeDef.mRenderables.push_back(std::move(renderable));
+ nodeDef.mRenderables[0]->mShaderIdx = 0;
- Context ctx;
- const auto VSH = "void main() { gl_Position = vec4(0.); }";
- const auto FSH = "void main() { gl_FragColor = vec4(1.); }";
- auto shader = Shader::New(VSH, FSH);
- ctx.resources.mShaders.push_back({ ShaderDefinition{}, shader });
+ Context ctx;
+ const auto VSH = "void main() { gl_Position = vec4(0.); }";
+ const auto FSH = "void main() { gl_FragColor = vec4(1.); }";
+ auto shader = Shader::New(VSH, FSH);
+ ctx.resources.mShaders.push_back({ShaderDefinition{}, shader});
auto actor = nodeDef.CreateActor(ctx.createParams);
DALI_TEST_EQUAL(1, actor.GetRendererCount());
if(renderer)
{
TextureSet textureSet = renderer.GetTextures();
- if(textureSet.GetTextureCount() == 7u)
+ if(textureSet.GetTextureCount() == 9u)
{
- texture = textureSet.GetTexture(5u);
+ texture = textureSet.GetTexture(7u);
}
}
}
if(renderer)
{
TextureSet textureSet = renderer.GetTextures();
- if(textureSet.GetTextureCount() == 7u)
+ if(textureSet.GetTextureCount() == 9u)
{
- texture = textureSet.GetTexture(6u);
+ texture = textureSet.GetTexture(8u);
}
}
}
Context ctx;
NodeDefinition nodeDef;
- nodeDef.mRenderable.reset(new NodeDefinition::Renderable());
+ std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(new NodeDefinition::Renderable());
+ nodeDef.mRenderables.push_back(std::move(renderable));
- DALI_TEST_EQUAL(INVALID_INDEX, ctx.factory.ProduceShader(nodeDef));
DALI_TEST_CHECK(ctx.resources.mShaders.empty());
END_TEST;
for(auto& ps : permSets)
{
- auto modelNode = new ModelNode();
- modelNode->mMeshIdx = 0;
- modelNode->mMaterialIdx = 0;
+ auto modelRenderable = new ModelRenderable();
+ modelRenderable->mMeshIdx = 0;
+ modelRenderable->mMaterialIdx = 0;
NodeDefinition nodeDef;
- nodeDef.mRenderable.reset(modelNode);
+ std::unique_ptr<NodeDefinition::Renderable> renderable;
+ renderable.reset(modelRenderable);
+ nodeDef.mRenderables.push_back(std::move(renderable));
auto& meshDef = NewMeshDefinition(ctx.resources);
auto& materialDef = NewMaterialDefinition(ctx.resources);
rendererState = (rendererState | p->rendererStateSet) & ~p->rendererStateClear;
}
- auto shaderIdx = ctx.factory.ProduceShader(nodeDef);
- DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx);
+ for(auto& renderable : nodeDef.mRenderables)
+ {
+ auto shaderIdx = ctx.factory.ProduceShader(*renderable);
+ DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx);
- auto& shaderDef = ctx.resources.mShaders[shaderIdx].first;
- DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState);
+ auto& shaderDef = ctx.resources.mShaders[shaderIdx].first;
+ DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState);
- uint32_t definesUnmatched = shaderDef.mDefines.size();
- for(auto& define : shaderDef.mDefines)
- {
- auto iFind = defines.find(define);
- if(iFind != defines.end())
- {
- defines.erase(iFind);
- --definesUnmatched;
- }
- else
+ uint32_t definesUnmatched = shaderDef.mDefines.size();
+ for(auto& define : shaderDef.mDefines)
{
- break;
+ auto iFind = defines.find(define);
+ if(iFind != defines.end())
+ {
+ defines.erase(iFind);
+ --definesUnmatched;
+ }
+ else
+ {
+ break;
+ }
}
- }
- DALI_TEST_CHECK(defines.empty());
- DALI_TEST_EQUAL(0, definesUnmatched);
+ DALI_TEST_CHECK(defines.empty());
+ DALI_TEST_EQUAL(0, definesUnmatched);
- auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"];
- DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT);
+ auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"];
+ DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT);
- auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"];
- DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX);
+ auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"];
+ DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX);
+ }
ClearMeshesAndMaterials(ctx.resources);
}
bool isAutoScroll = false;
bool isAutoScrollMaxTextureExceeded = false;
+ bool isHiddenInputEnabled = false;
layoutEngine.LayoutText(layoutParameters,
layoutSize,
false,
isAutoScroll,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition);
if(options.align)
bool isAutoScroll = false;
bool isAutoScrollMaxTextureExceeded = false;
+ bool isHiddenInputEnabled = false;
const bool updated = engine.LayoutText(layoutParameters,
layoutSize,
data.ellipsis,
isAutoScroll,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
DevelText::EllipsisPosition::END);
// 4) Compare the results.
bool isAutoScroll = false;
bool isAutoScrollMaxTextureExceeded = false;
+ bool isHiddenInputEnabled = false;
const bool updated = engine.LayoutText(layoutParameters,
layoutSize,
data.ellipsis,
isAutoScroll,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
data.ellipsisPosition);
// 4) Compare the results.
namespace
{
const char* TEST_VECTOR_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/insta_camera.json";
+const char* TEST_GIF_FILE_NAME = TEST_RESOURCE_DIR "/anim.gif";
-}
+} // namespace
int UtcDaliVisualAction(void)
{
END_TEST;
}
+int UtcDaliAnimatedImageVisualCreateInstancePropertyMap(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliAnimatedImageVisualCreateInstancePropertyMap");
+
+ Property::Map propertyMap;
+ propertyMap.Add(Toolkit::Visual::Property::TYPE, Visual::ANIMATED_IMAGE)
+ .Add(ImageVisual::Property::URL, TEST_GIF_FILE_NAME)
+ .Add(ImageVisual::Property::DESIRED_WIDTH, 10)
+ .Add(ImageVisual::Property::DESIRED_HEIGHT, 12);
+
+ // request AnimatedVectorImageVisual with a property map
+ VisualFactory factory = VisualFactory::Get();
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ Toolkit::Internal::Visual::Base& visualImpl = GetImplementation(visual);
+
+ Property::Map resultMap;
+ visualImpl.CreateInstancePropertyMap(resultMap);
+
+ // check the property values from the returned map from a visual
+ DALI_TEST_EQUALS(resultMap.Count(), 3u, TEST_LOCATION);
+
+ Property::Value* value = resultMap.Find(Toolkit::Visual::Property::TYPE, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == Visual::ANIMATED_IMAGE);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::DESIRED_WIDTH, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == 10);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == 12);
+
+ END_TEST;
+}
+
int UtcDaliAnimatedVectorImageVisualSetProperties(void)
{
ToolkitTestApplication application;
return true;
}
+bool TestGlAbstraction::IsMultisampledRenderToTextureSupported()
+{
+ return true;
+}
+
bool TestGlAbstraction::IsBlendEquationSupported(DevelBlendEquation::Type blendEquation)
{
return true;
bool IsAdvancedBlendEquationSupported() override;
+ bool IsMultisampledRenderToTextureSupported() override;
+
bool IsBlendEquationSupported(DevelBlendEquation::Type blendEquation) override;
std::string GetShaderVersionPrefix();
{
}
+ inline void FramebufferTexture2DMultisample(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) override
+ {
+ // TODO : Check it if need
+ FramebufferTexture2D(target, attachment, textarget, texture, level);
+ }
+
inline void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) override
{
}
.Add(ImageVisual::Property::PIXEL_AREA, Vector4())
.Add(ImageVisual::Property::WRAP_MODE_U, WrapMode::REPEAT)
.Add(ImageVisual::Property::WRAP_MODE_V, WrapMode::DEFAULT)
+ .Add(ImageVisual::Property::FITTING_MODE, FittingMode::FIT_WIDTH)
+ .Add(ImageVisual::Property::SAMPLING_MODE, SamplingMode::NEAREST)
+ .Add(ImageVisual::Property::DESIRED_WIDTH, 154)
+ .Add(ImageVisual::Property::DESIRED_HEIGHT, 79)
.Add(ImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME)
.Add(ImageVisual::Property::MASK_CONTENT_SCALE, 1.6f)
.Add(ImageVisual::Property::CROP_TO_MASK, true)
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<std::string>() == TEST_GIF_FILE_NAME);
+ value = resultMap.Find(Toolkit::ImageVisual::Property::WRAP_MODE_U, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == WrapMode::REPEAT);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::WRAP_MODE_V, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == WrapMode::DEFAULT);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::FITTING_MODE, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == FittingMode::FIT_WIDTH);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::SAMPLING_MODE, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == SamplingMode::NEAREST);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::DESIRED_WIDTH, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == 154);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == 79);
+
value = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
DALI_TEST_CHECK(value);
DALI_TEST_EQUALS(value->Get<Vector4>(), Vector4(22.2f, 22.2f, 22.2f, 22.2f), TEST_LOCATION);
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<int>() == DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+ // Natural size getted as desired size
Vector2 naturalSize;
animatedImageVisual.GetNaturalSize(naturalSize);
- DALI_TEST_EQUALS(naturalSize, Vector2(100, 100), TEST_LOCATION);
+ DALI_TEST_EQUALS(naturalSize, Vector2(154, 79), TEST_LOCATION);
// request AnimatedImageVisual with an URL
Visual::Base animatedImageVisual2 = factory.CreateVisual(TEST_GIF_FILE_NAME, ImageDimensions());
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<std::string>() == TEST_GIF_FILE_NAME);
+ // Natural size getted as image size
+ animatedImageVisual2.GetNaturalSize(naturalSize);
+ DALI_TEST_EQUALS(naturalSize, Vector2(50, 50), TEST_LOCATION);
+
END_TEST;
}
.Add("pixelArea", Vector4())
.Add("wrapModeU", WrapMode::REPEAT)
.Add("wrapModeV", WrapMode::DEFAULT)
+ .Add("fittingMode", FittingMode::FIT_WIDTH)
+ .Add("samplingMode", SamplingMode::NEAREST)
+ .Add("desiredWidth", 154)
+ .Add("desiredHeight", 79)
.Add("alphaMaskUrl", TEST_MASK_IMAGE_FILE_NAME)
.Add("maskContentScale", 1.6f)
.Add("cropToMask", true)
DALI_TEST_CHECK(value);
DALI_TEST_EQUALS(value->Get<int>(), 11, TEST_LOCATION);
+ value = resultMap.Find(Toolkit::ImageVisual::Property::WRAP_MODE_U, "wrapModeU");
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == WrapMode::REPEAT);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::WRAP_MODE_V, "wrapModeV");
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == WrapMode::DEFAULT);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::FITTING_MODE, "fittingMode");
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == FittingMode::FIT_WIDTH);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::SAMPLING_MODE, "samplingMode");
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == SamplingMode::NEAREST);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::DESIRED_WIDTH, "desiredWidth");
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == 154);
+
+ value = resultMap.Find(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, "desiredHeight");
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<int>() == 79);
+
value = resultMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS, "cornerRadius");
DALI_TEST_CHECK(value);
DALI_TEST_EQUALS(value->Get<Vector4>(), Vector4(50.0f, 25.0f, 12.5f, 33.0f), TEST_LOCATION);
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<bool>() == DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+ // Natural size getted as masked image size
+ Vector2 naturalSize;
+ animatedImageVisual.GetNaturalSize(naturalSize);
+ DALI_TEST_EQUALS(naturalSize, Vector2(100, 100), TEST_LOCATION);
+
END_TEST;
}
// Test wrap mode in animated image visual.
const int width = 950;
const int height = 1080;
- const Vector4 pixelArea(0.0f, 0.0f, 950/ 40, 1.0f);
+ const Vector4 pixelArea(0.0f, 0.0f, 950 / 40, 1.0f);
Property::Map propertyMap;
propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
END_TEST;
}
+
+int UtcDaliAnimatedImageVisualDesiredSize(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliAnimatedImageVisualDesiredSize");
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+
+ // Set desiredWidth < 37 and desiredHeight < 50, which is smaller than original image's size.
+ int desiredWidth = 15;
+ int desiredHeight = 20;
+
+ Visual::Base visual = VisualFactory::Get().CreateVisual(TEST_GIF_FILE_NAME, ImageDimensions(desiredWidth, desiredHeight));
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New(true);
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // Trigger count is 2 - first frame and second frame.
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+ textureTrace.Enable(true);
+ textureTrace.EnableLogging(true);
+
+ application.SendNotification();
+ application.Render();
+
+ {
+ std::stringstream out;
+ out << GL_TEXTURE_2D << ", " << 0u << ", " << desiredWidth << ", " << desiredHeight;
+ DALI_TEST_CHECK(textureTrace.FindMethodAndParams("TexImage2D", out.str().c_str()));
+ }
+
+ // Unparent to make next trigger
+ actor.Unparent();
+
+ application.SendNotification();
+ application.Render();
+
+ // Set visual size
+ actor.SetProperty(Actor::Property::SIZE, Vector2(300.0f, 300.0f));
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // Trigger count is 2 - first frame and second frame.
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+ textureTrace.Reset();
+
+ application.SendNotification();
+ application.Render();
+
+ {
+ std::stringstream out;
+ out << GL_TEXTURE_2D << ", " << 0u << ", " << desiredWidth << ", " << desiredHeight;
+ DALI_TEST_CHECK(textureTrace.FindMethodAndParams("TexImage2D", out.str().c_str())); // The size should not be changed
+ }
+
+ END_TEST;
+}
\ No newline at end of file
application.Render();
field.SetProperty(TextField::Property::TEXT, "Hello");
+ field.SetProperty(TextField::Property::PLACEHOLDER_TEXT, "Placeholder text");
field.SetProperty(TextField::Property::POINT_SIZE, 10.f);
field.SetProperty(Actor::Property::SIZE, Vector2(300.f, 50.f));
field.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
application.ProcessEvent(GenerateKey("d", "", "d", 0, 0, 0, Integration::KeyEvent::DOWN, "d", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
application.SendNotification();
application.Render();
+ for(unsigned int index = 0u; index < 6u; ++index)
+ {
+ application.ProcessEvent(GenerateKey("", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+ application.SendNotification();
+ application.Render();
+ }
map[HiddenInput::Property::MODE] = HiddenInput::Mode::HIDE_ALL;
map[HiddenInput::Property::SUBSTITUTE_CHARACTER] = 0x23;
#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/devel-api/rendering/frame-buffer-devel.h>
#include <dali/integration-api/debug.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/public-api/object/type-registry.h>
Property::Index RENDERING_BUFFER = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1;
constexpr int32_t DEFAULT_ORIENTATION = 0;
+constexpr uint8_t DEFAULT_FRAME_BUFFER_MULTI_SAMPLING_LEVEL = 4u;
+
static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity";
Dali::Actor CreateSkybox(const std::string& skyboxUrl)
UpdateCamera(GetCamera(name));
}
-void SceneView::RegisterSceneItem(Scene3D::Internal::ImageBasedLightObserver *item)
+void SceneView::RegisterSceneItem(Scene3D::Internal::ImageBasedLightObserver* item)
{
if(item)
{
}
}
-void SceneView::UnregisterSceneItem(Scene3D::Internal::ImageBasedLightObserver *item)
+void SceneView::UnregisterSceneItem(Scene3D::Internal::ImageBasedLightObserver* item)
{
if(item)
{
if(mRenderTask)
{
taskList.RemoveTask(mRenderTask);
- mRenderTarget.Reset();
+ mFrameBuffer.Reset();
}
}
mWindow.Reset();
mRenderTask.SetViewport(Dali::Viewport(Vector4::ZERO));
// create offscreen buffer of new size to render our child actors to
- mTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, unsigned(size.width), unsigned(size.height));
- mRenderTarget = FrameBuffer::New(size.width, size.height, FrameBuffer::Attachment::DEPTH_STENCIL);
- mRenderTarget.AttachColorTexture(mTexture);
- Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(mRenderTarget, 0u);
+ mTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, unsigned(size.width), unsigned(size.height));
+ mFrameBuffer = FrameBuffer::New(size.width, size.height, FrameBuffer::Attachment::DEPTH_STENCIL);
+ mFrameBuffer.AttachColorTexture(mTexture);
+ DevelFrameBuffer::SetMultiSamplingLevel(mFrameBuffer, DEFAULT_FRAME_BUFFER_MULTI_SAMPLING_LEVEL);
+ Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(mFrameBuffer, 0u);
Property::Map imagePropertyMap;
imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
Toolkit::DevelControl::RegisterVisual(*this, RENDERING_BUFFER, mVisual);
- mRenderTask.SetFrameBuffer(mRenderTarget);
+ mRenderTask.SetFrameBuffer(mFrameBuffer);
mRenderTask.SetClearEnabled(true);
mRenderTask.SetClearColor(Color::TRANSPARENT);
}
Toolkit::DevelControl::UnregisterVisual(*this, RENDERING_BUFFER);
mVisual.Reset();
- mRenderTarget.Reset();
+ mFrameBuffer.Reset();
mTexture.Reset();
}
}
CameraActor mSelectedCamera;
std::vector<CameraActor> mCameras;
std::vector<Scene3D::Internal::ImageBasedLightObserver*> mItems;
- Dali::FrameBuffer mRenderTarget;
+ Dali::FrameBuffer mFrameBuffer;
Dali::Texture mTexture;
Dali::RenderTask mRenderTask;
Layer mRootLayer;
#endif //GLTF_CHANNELS
#endif //THREE_TEX
-uniform lowp vec4 uColorFactor;
+uniform lowp vec4 uColor; // Color from SceneGraph
+uniform lowp vec4 uColorFactor; // Color from material
uniform lowp float uMetallicFactor;
uniform lowp float uRoughnessFactor;
+uniform lowp float uDielectricSpecular;
#ifdef THREE_TEX
#ifdef BASECOLOR_TEX
uniform sampler2D sNormalRoughness;
#endif
+uniform float uSpecularFactor;
+uniform vec3 uSpecularColorFactor;
+#ifdef MATERIAL_SPECULAR_TEXTURE
+uniform sampler2D sSpecular;
+#endif
+#ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
+uniform sampler2D sSpecularColor;
+#endif
+
#ifdef OCCLUSION
uniform sampler2D sOcclusion;
uniform float uOcclusionStrength;
out vec4 FragColor;
-struct PBRInfo
-{
- mediump float NdotL; // cos angle between normal and light direction
- mediump float NdotV; // cos angle between normal and view direction
- mediump float NdotH; // cos angle between normal and half vector
- mediump float VdotH; // cos angle between view direction and half vector
- mediump vec3 reflectance0; // full reflectance color (normal incidence angle)
- mediump vec3 reflectance90; // reflectance color at grazing angle
- lowp float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])
-};
-
-const float M_PI = 3.141592653589793;
const float c_MinRoughness = 0.04;
-vec3 specularReflection(PBRInfo pbrInputs)
-{
- return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
-}
-
-float geometricOcclusion(PBRInfo pbrInputs)
-{
- mediump float NdotL = pbrInputs.NdotL;
- mediump float NdotV = pbrInputs.NdotV;
- lowp float r = pbrInputs.alphaRoughness;
-
- lowp float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
- lowp float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
- return attenuationL * attenuationV;
-}
-
-float microfacetDistribution(PBRInfo pbrInputs)
-{
- mediump float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
- lowp float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
- return roughnessSq / (M_PI * f * f);
-}
-
vec3 linear(vec3 color)
{
return pow(color, vec3(2.2));
// Roughness is authored as perceptual roughness; as is convention,
// convert to material roughness by squaring the perceptual roughness [2].
perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
- lowp float alphaRoughness = perceptualRoughness * perceptualRoughness;
-
- lowp vec3 f0 = vec3(0.04);
- lowp vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
- diffuseColor *= (1.0 - metallic);
- lowp vec3 specularColor = mix(f0, baseColor.rgb, metallic);
- // Compute reflectance.
- lowp float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
+ // Material ior
+ lowp vec3 f0 = vec3(uDielectricSpecular);
- // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
- // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
- lowp float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
- lowp vec3 specularEnvironmentR0 = specularColor.rgb;
- lowp vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
+ // Material Specular
+ float specularWeight = 1.0;
+ vec4 materialSpecularTexture = vec4(1.0);
+#ifdef MATERIAL_SPECULAR_TEXTURE
+ materialSpecularTexture.a = texture(sSpecular, vUV).a;
+#endif
+#ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
+ materialSpecularTexture.rgb = texture(sSpecularColor, vUV).rgb;
+#endif
+ specularWeight = uSpecularFactor * materialSpecularTexture.a;
+ f0 = min(f0 * uSpecularColorFactor * materialSpecularTexture.rgb, vec3(1.0));
+ f0 = mix(f0, baseColor.rgb, metallic);
mediump vec3 v = normalize(vPositionToCamera); // Vector from surface point to camera
mediump float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
mediump vec3 reflection = -normalize(reflect(v, n));
+ lowp vec3 brdf = linear(texture(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb);
+ vec3 Fr = max(vec3(1.0 - perceptualRoughness), f0) - f0;
+ vec3 k_S = f0 + Fr * pow(1.0 - NdotV, 5.0);
+ vec3 FssEss = specularWeight * (k_S * brdf.x + brdf.y);
- lowp vec3 color = vec3(0.0);
- lowp vec3 diffuseLight = linear(texture(sDiffuseEnvSampler, n * uYDirection).rgb);
+ // Specular Light
lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection * uYDirection).rgb);
- // retrieve a scale and bias to F0. See [1], Figure 3
- lowp vec3 brdf = linear(texture(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb);
+ lowp vec3 specular = specularLight * FssEss;
+
+ // Diffuse Light
+ lowp vec3 diffuseColor = mix(baseColor.rgb, vec3(0), metallic);
+ lowp vec3 irradiance = linear(texture(sDiffuseEnvSampler, n * uYDirection).rgb);
+ float Ems = (1.0 - (brdf.x + brdf.y));
+ vec3 F_avg = specularWeight * (f0 + (1.0 - f0) / 21.0);
+ vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);
+ vec3 k_D = diffuseColor * (1.0 - FssEss + FmsEms);
+ lowp vec3 diffuse = (FmsEms + k_D) * irradiance;
- lowp vec3 diffuse = diffuseLight * diffuseColor;
- lowp vec3 specular = specularLight * (specularColor * brdf.x + brdf.y);
- color += (diffuse + specular) * uIblIntensity;
+ lowp vec3 color = (diffuse + specular) * uIblIntensity;
#ifdef OCCLUSION
lowp float ao = texture(sOcclusion, vUV).r;
color += emissive;
#endif // EMISSIVE
- FragColor = vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a);
+ FragColor = vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a) * uColor;
}
#version 300 es
precision mediump float;
+uniform lowp vec4 uColor;
flat in float vColor;
out vec4 FragColor;
void main()
{
vec3 rgb = vec3(fract(vColor), fract(vColor * 0.00390625), fract(vColor * 0.00390625 * 0.00390625));
- FragColor = vec4(rgb, 1.);
+ FragColor = vec4(rgb, 1.) * uColor;
}
\ No newline at end of file
uniform samplerCube uSkyBoxTexture;
+uniform lowp vec4 uColor;
uniform mediump float uIntensity;
varying mediump vec3 vTexCoord;
void main()
{
mediump vec4 texColor = textureCube(uSkyBoxTexture, vTexCoord) * uIntensity;
- gl_FragColor = texColor;
+ gl_FragColor = texColor * uColor;
}
\ No newline at end of file
}
};
+/**
+ * Material Ior is supported with KHR_materials_ior extension.
+ * https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_ior
+ */
+struct MaterialIor
+{
+ float mIor = MAXFLOAT;
+};
+
+/**
+ * Material Specular is supported with KHR_materials_ior extension.
+ * https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_specular
+ */
+struct MaterialSpecular
+{
+ float mSpecularFactor = 1.0f;
+ TextureInfo mSpecularTexture;
+ Dali::Vector3 mSpecularColorFactor = Dali::Vector3::ONE;
+ TextureInfo mSpecularColorTexture;
+};
+
+struct MaterialExtensions
+{
+ MaterialSpecular mMaterialSpecular;
+ MaterialIor mMaterialIor;
+};
+
struct Material : Named
{
- struct Pbr //MetallicRoughness
+ struct Pbr // MetallicRoughness
{
Dali::Vector4 mBaseColorFactor = Dali::Vector4::ONE;
TextureInfo mBaseColorTexture;
//TODO: extras
};
- Pbr mPbrMetallicRoughness;
- TextureInfo mNormalTexture;
- TextureInfo mOcclusionTexture;
- TextureInfo mEmissiveTexture;
- Dali::Vector3 mEmissiveFactor;
- AlphaMode::Type mAlphaMode = AlphaMode::OPAQUE;
- float mAlphaCutoff = .5f;
- bool mDoubleSided = false;
- //TODO: extensions
+ Pbr mPbrMetallicRoughness;
+ TextureInfo mNormalTexture;
+ TextureInfo mOcclusionTexture;
+ TextureInfo mEmissiveTexture;
+ Dali::Vector3 mEmissiveFactor;
+ AlphaMode::Type mAlphaMode = AlphaMode::OPAQUE;
+ float mAlphaCutoff = .5f;
+ bool mDoubleSided = false;
+
+ //extensions
+ MaterialExtensions mMaterialExtensions;
//TODO: extras
};
}
///@brief Reads arc properties.
-void ReadArcField(const TreeNode* eArc, ArcNode& arc)
+void ReadArcField(const TreeNode* eArc, ArcRenderable& arc)
{
ReadBool(eArc->GetChild("antiAliasing"), arc.mAntiAliasing);
ReadInt(eArc->GetChild("arcCaps"), arc.mArcCaps);
}
}
-} //namespace
+} // namespace
struct DliLoader::Impl
{
void DliLoader::Impl::ParseSceneInternal(Index iScene, const Toolkit::TreeNode* tnScenes, const Toolkit::TreeNode* tnNodes, LoadParams& params)
{
- auto getSceneRootIdx = [tnScenes, tnNodes](Index iScene) {
+ auto getSceneRootIdx = [tnScenes, tnNodes](Index iScene)
+ {
auto tn = GetNthChild(tnScenes, iScene); // now a "scene" object
if(!tn)
{
uint32_t jointCount = 0;
std::function<void(Index)> visitFn;
auto& ibms = mInverseBindMatrices;
- visitFn = [&](Index id) {
+ visitFn = [&](Index id)
+ {
auto node = scene.GetNode(id);
jointCount += ibms.find(id) != ibms.end();
skeleton.mJoints.reserve(jointCount);
- visitFn = [&](Index id) {
+ visitFn = [&](Index id)
+ {
auto iFind = ibms.find(id);
if(iFind != ibms.end() && skeleton.mJoints.size() < Skinning::MAX_JOINTS)
{
}
}
- //TODO : need to consider AGIF
+ // TODO : need to consider AGIF
std::vector<std::string> texturePaths;
std::string texturePath;
if(ReadString(node.GetChild("albedoMap"), texturePath))
virtual unsigned int Resolve(Index iDli) override
{
- auto iFind = std::lower_bound(mIndices.begin(), mIndices.end(), iDli, [](const Entry& idx, Index iDli) {
- return idx.iDli < iDli;
- });
+ auto iFind = std::lower_bound(mIndices.begin(), mIndices.end(), iDli, [](const Entry& idx, Index iDli)
+ { return idx.iDli < iDli; });
DALI_ASSERT_ALWAYS(iFind != mIndices.end());
return iFind->iScene;
}
else // something renderable maybe
{
std::unique_ptr<NodeDefinition::Renderable> renderable;
- ModelNode* modelNode = nullptr; // no ownership, aliasing renderable for the right type.
+ ModelRenderable* modelRenderable = nullptr; // no ownership, aliasing renderable for the right type.
const TreeNode* eRenderable = nullptr;
if((eRenderable = node->GetChild("model")))
ExceptionFlinger(ASSERT_LOCATION) << "node " << nodeDef.mName << ": Missing mesh definition.";
}
- modelNode = new ModelNode();
- renderable.reset(modelNode);
+ modelRenderable = new ModelRenderable();
+ renderable.reset(modelRenderable);
- resourceIds.push_back({ResourceType::Mesh, eMesh, modelNode->mMeshIdx});
+ resourceIds.push_back({ResourceType::Mesh, eMesh, modelRenderable->mMeshIdx});
}
else if((eRenderable = node->GetChild("arc")))
{
ExceptionFlinger(ASSERT_LOCATION) << "node " << nodeDef.mName << ": Missing mesh definition.";
}
- auto arcNode = new ArcNode;
- renderable.reset(arcNode);
- modelNode = arcNode;
+ auto arcRenderable = new ArcRenderable;
+ renderable.reset(arcRenderable);
+ modelRenderable = arcRenderable;
- resourceIds.push_back({ResourceType::Mesh, eMesh, arcNode->mMeshIdx});
+ resourceIds.push_back({ResourceType::Mesh, eMesh, arcRenderable->mMeshIdx});
- ReadArcField(eRenderable, *arcNode);
+ ReadArcField(eRenderable, *arcRenderable);
}
if(renderable && eRenderable != nullptr) // process common properties of all renderables + register payload
}
// color
- if(modelNode)
+ if(modelRenderable)
{
- modelNode->mMaterialIdx = 0; // must offer default of 0
- auto eMaterial = eRenderable->GetChild("material");
+ modelRenderable->mMaterialIdx = 0; // must offer default of 0
+ auto eMaterial = eRenderable->GetChild("material");
if(eMaterial)
{
- resourceIds.push_back({ResourceType::Material, eMaterial, modelNode->mMaterialIdx});
+ resourceIds.push_back({ResourceType::Material, eMaterial, modelRenderable->mMaterialIdx});
}
- if(!ReadColorCodeOrColor(eRenderable, modelNode->mColor, params.input.mConvertColorCode))
+ if(!ReadColorCodeOrColor(eRenderable, modelRenderable->mColor, params.input.mConvertColorCode))
{
- ReadColorCodeOrColor(node, modelNode->mColor, params.input.mConvertColorCode);
+ ReadColorCodeOrColor(node, modelRenderable->mColor, params.input.mConvertColorCode);
}
}
- nodeDef.mRenderable = std::move(renderable);
+ nodeDef.mRenderables.push_back(std::move(renderable));
}
}
AnimationDefinition animDef;
ReadString(tnAnim.GetChild(NAME), animDef.mName);
- auto iFind = std::lower_bound(definitions.begin(), definitions.end(), animDef, [](const AnimationDefinition& ad0, const AnimationDefinition& ad1) {
- return ad0.mName < ad1.mName;
- });
+ auto iFind = std::lower_bound(definitions.begin(), definitions.end(), animDef, [](const AnimationDefinition& ad0, const AnimationDefinition& ad1)
+ { return ad0.mName < ad1.mName; });
const bool overwrite = iFind != definitions.end() && iFind->mName == animDef.mName;
if(overwrite)
{
animProp.mKeyFrames = KeyFrames::New();
- //In binary animation file only is saved the position, rotation, scale and blend shape weight keys.
- //so, if it is vector3 we assume is position or scale keys, if it is vector4 we assume is rotation,
- // otherwise are blend shape weight keys.
- // TODO support for binary header with size information
+ // In binary animation file only is saved the position, rotation, scale and blend shape weight keys.
+ // so, if it is vector3 we assume is position or scale keys, if it is vector4 we assume is rotation,
+ // otherwise are blend shape weight keys.
+ // TODO support for binary header with size information
Property::Type propType = Property::FLOAT; // assume blend shape weights
if(animProp.mPropertyName == "orientation")
{
propType = Property::VECTOR3;
}
- //alphafunction is reserved for future implementation
- // NOTE: right now we're just using AlphaFunction::LINEAR.
+ // alphafunction is reserved for future implementation
+ // NOTE: right now we're just using AlphaFunction::LINEAR.
unsigned char dummyAlphaFunction;
float progress;
continue;
}
- auto iFind = std::lower_bound(animGroups.begin(), animGroups.end(), groupName, [](const AnimationGroupDefinition& group, const std::string& name) {
- return group.mName < name;
- });
+ auto iFind = std::lower_bound(animGroups.begin(), animGroups.end(), groupName, [](const AnimationGroupDefinition& group, const std::string& name)
+ { return group.mName < name; });
if(iFind != animGroups.end() && iFind->mName == groupName)
{
mOnError(FormatString("Animation group with name '%s' already exists; new entries will be merged.", groupName.c_str()));
* limitations under the License.
*
*/
-#include "dali-scene3d/public-api/loader/gltf2-loader.h"
#include <fstream>
-#include "dali-scene3d/internal/loader/gltf2-asset.h"
-#include "dali-scene3d/public-api/loader/load-result.h"
-#include "dali-scene3d/public-api/loader/resource-bundle.h"
-#include "dali-scene3d/public-api/loader/scene-definition.h"
-#include "dali-scene3d/public-api/loader/shader-definition-factory.h"
-#include "dali-scene3d/public-api/loader/utils.h"
-#include "dali/public-api/math/quaternion.h"
+#include <dali-scene3d/public-api/loader/gltf2-loader.h>
+#include <dali-scene3d/internal/loader/gltf2-asset.h>
+#include <dali-scene3d/public-api/loader/load-result.h>
+#include <dali-scene3d/public-api/loader/resource-bundle.h>
+#include <dali-scene3d/public-api/loader/scene-definition.h>
+#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
+#include <dali-scene3d/public-api/loader/utils.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/integration-api/debug.h>
#define ENUM_STRING_MAPPING(t, x) \
{ \
.Register(*js::MakeProperty("roughnessFactor", js::Read::Number<float>, >::Material::Pbr::mRoughnessFactor))
.Register(*js::MakeProperty("metallicRoughnessTexture", js::ObjectReader<gt::TextureInfo>::Read, >::Material::Pbr::mMetallicRoughnessTexture)));
+const auto MATERIAL_SPECULAR_READER = std::move(js::Reader<gt::MaterialSpecular>()
+ .Register(*js::MakeProperty("specularFactor", js::Read::Number<float>, >::MaterialSpecular::mSpecularFactor))
+ .Register(*js::MakeProperty("specularTexture", js::ObjectReader<gt::TextureInfo>::Read, >::MaterialSpecular::mSpecularTexture))
+ .Register(*js::MakeProperty("specularColorFactor", gt::ReadDaliVector<Vector3>, >::MaterialSpecular::mSpecularColorFactor))
+ .Register(*js::MakeProperty("specularColorTexture", js::ObjectReader<gt::TextureInfo>::Read, >::MaterialSpecular::mSpecularColorTexture)));
+
+const auto MATERIAL_IOR_READER = std::move(js::Reader<gt::MaterialIor>()
+ .Register(*js::MakeProperty("ior", js::Read::Number<float>, >::MaterialIor::mIor)));
+
+
+const auto MATERIAL_EXTENSION_READER = std::move(js::Reader<gt::MaterialExtensions>()
+ .Register(*js::MakeProperty("KHR_materials_ior", js::ObjectReader<gt::MaterialIor>::Read, >::MaterialExtensions::mMaterialIor))
+ .Register(*js::MakeProperty("KHR_materials_specular", js::ObjectReader<gt::MaterialSpecular>::Read, >::MaterialExtensions::mMaterialSpecular)));
+
const auto MATERIAL_READER = std::move(js::Reader<gt::Material>()
.Register(*new js::Property<gt::Material, std::string_view>("name", js::Read::StringView, >::Material::mName))
.Register(*js::MakeProperty("pbrMetallicRoughness", js::ObjectReader<gt::Material::Pbr>::Read, >::Material::mPbrMetallicRoughness))
.Register(*js::MakeProperty("emissiveTexture", js::ObjectReader<gt::TextureInfo>::Read, >::Material::mEmissiveTexture))
.Register(*js::MakeProperty("emissiveFactor", gt::ReadDaliVector<Vector3>, >::Material::mEmissiveFactor))
.Register(*js::MakeProperty("alphaMode", gt::ReadStringEnum<gt::AlphaMode>, >::Material::mAlphaMode))
- .Register(*js::MakeProperty("alphaCutoff", js::Read::Number<float>, >::Material::mAlphaCutoff)));
+ .Register(*js::MakeProperty("alphaCutoff", js::Read::Number<float>, >::Material::mAlphaCutoff))
+ .Register(*js::MakeProperty("doubleSided", js::Read::Boolean, >::Material::mDoubleSided))
+ .Register(*js::MakeProperty("extensions", js::ObjectReader<gt::MaterialExtensions>::Read, >::Material::mMaterialExtensions)));
std::map<gt::Attribute::Type, gt::Ref<gt::Accessor>> ReadMeshPrimitiveAttributes(const json_value_s& j)
{
return TextureDefinition{std::string(mm.mTexture->mSource->mUri), ConvertSampler(mm.mTexture->mSampler)};
}
-void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)& outMaterials)
+void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMaterials)& outMaterials)
{
MaterialDefinition matDef;
- auto& pbr = m.mPbrMetallicRoughness;
- if(m.mAlphaMode != gt::AlphaMode::OPAQUE || pbr.mBaseColorFactor.a < 1.f)
+ auto& pbr = material.mPbrMetallicRoughness;
+ if(pbr.mBaseColorFactor.a < 1.f)
{
matDef.mFlags |= MaterialDefinition::TRANSPARENCY;
}
- if(m.mAlphaMode == gt::AlphaMode::MASK)
+ if(material.mAlphaMode == gt::AlphaMode::MASK)
{
- matDef.SetAlphaCutoff(std::min(1.f, std::max(0.f, m.mAlphaCutoff)));
+ matDef.SetAlphaCutoff(std::min(1.f, std::max(0.f, material.mAlphaCutoff)));
}
matDef.mBaseColorFactor = pbr.mBaseColorFactor;
- matDef.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!m.mNormalTexture + !!m.mOcclusionTexture + !!m.mEmissiveTexture);
+ matDef.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!material.mNormalTexture + !!material.mOcclusionTexture + !!material.mEmissiveTexture);
if(pbr.mBaseColorTexture)
{
const auto semantic = MaterialDefinition::ALBEDO;
matDef.mNeedMetallicRoughnessTexture = false;
}
- matDef.mNormalScale = m.mNormalTexture.mScale;
- if(m.mNormalTexture)
+ matDef.mNormalScale = material.mNormalTexture.mScale;
+ if(material.mNormalTexture)
{
const auto semantic = MaterialDefinition::NORMAL;
- matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mNormalTexture)});
+ matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mNormalTexture)});
// TODO: and there had better be one
matDef.mFlags |= semantic;
}
matDef.mNeedNormalTexture = false;
}
- // TODO: handle doubleSided
- if(m.mOcclusionTexture)
+ if(material.mOcclusionTexture)
{
const auto semantic = MaterialDefinition::OCCLUSION;
- matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mOcclusionTexture)});
+ matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mOcclusionTexture)});
// TODO: and there had better be one
matDef.mFlags |= semantic;
- matDef.mOcclusionStrength = m.mOcclusionTexture.mStrength;
+ matDef.mOcclusionStrength = material.mOcclusionTexture.mStrength;
}
- if(m.mEmissiveTexture)
+ if(material.mEmissiveTexture)
{
const auto semantic = MaterialDefinition::EMISSIVE;
- matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mEmissiveTexture)});
+ matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mEmissiveTexture)});
// TODO: and there had better be one
matDef.mFlags |= semantic;
- matDef.mEmissiveFactor = m.mEmissiveFactor;
+ matDef.mEmissiveFactor = material.mEmissiveFactor;
+ }
+
+ if(material.mMaterialExtensions.mMaterialIor.mIor < MAXFLOAT)
+ {
+ float ior = material.mMaterialExtensions.mMaterialIor.mIor;
+ matDef.mDielectricSpecular = powf((ior-1.0f)/(ior+1.0f), 2.0f);
}
+ matDef.mSpecularFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularFactor;
+ matDef.mSpecularColorFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularColorFactor;
+
+ if(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture)
+ {
+ const auto semantic = MaterialDefinition::SPECULAR;
+ matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture)});
+ matDef.mFlags |= semantic;
+ }
+
+ if(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture)
+ {
+ const auto semantic = MaterialDefinition::SPECULAR_COLOR;
+ matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture)});
+ matDef.mFlags |= semantic;
+ }
+
+ matDef.mDoubleSided = material.mDoubleSided;
outMaterials.emplace_back(std::move(matDef), TextureSet());
}
-void ConvertMaterials(const gt::Document& doc, ConversionContext& cctx)
+void ConvertMaterials(const gt::Document& doc, ConversionContext& context)
{
- auto& outMaterials = cctx.mOutput.mResources.mMaterials;
+ auto& outMaterials = context.mOutput.mResources.mMaterials;
outMaterials.reserve(doc.mMaterials.size());
for(auto& m : doc.mMaterials)
std::move(sparseBlob)};
}
-void ConvertMeshes(const gt::Document& doc, ConversionContext& cctx)
+void ConvertMeshes(const gt::Document& doc, ConversionContext& context)
{
uint32_t meshCount = 0;
- cctx.mMeshIds.reserve(doc.mMeshes.size());
- for(auto& m : doc.mMeshes)
+ context.mMeshIds.reserve(doc.mMeshes.size());
+ for(auto& mesh : doc.mMeshes)
{
- cctx.mMeshIds.push_back(meshCount);
- meshCount += m.mPrimitives.size();
+ context.mMeshIds.push_back(meshCount);
+ meshCount += mesh.mPrimitives.size();
}
- auto& outMeshes = cctx.mOutput.mResources.mMeshes;
+ auto& outMeshes = context.mOutput.mResources.mMeshes;
outMeshes.reserve(meshCount);
- for(auto& m : doc.mMeshes)
+ for(auto& mesh : doc.mMeshes)
{
- for(auto& p : m.mPrimitives)
+ for(auto& primitive : mesh.mPrimitives)
{
- MeshDefinition meshDef;
+ MeshDefinition meshDefinition;
- auto& attribs = p.mAttributes;
- meshDef.mUri = attribs.begin()->second->mBufferView->mBuffer->mUri;
- meshDef.mPrimitiveType = GLTF2_TO_DALI_PRIMITIVES[p.mMode];
+ auto& attribs = primitive.mAttributes;
+ meshDefinition.mUri = attribs.begin()->second->mBufferView->mBuffer->mUri;
+ meshDefinition.mPrimitiveType = GLTF2_TO_DALI_PRIMITIVES[primitive.mMode];
auto& accPositions = *attribs.find(gt::Attribute::POSITION)->second;
- meshDef.mPositions = ConvertMeshPrimitiveAccessor(accPositions);
+ meshDefinition.mPositions = ConvertMeshPrimitiveAccessor(accPositions);
// glTF2 support vector4 tangent for mesh.
// https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#meshes-overview
- meshDef.mTangentType = Property::VECTOR4;
+ meshDefinition.mTangentType = Property::VECTOR4;
const bool needNormalsTangents = accPositions.mType == gt::AccessorType::VEC3;
for(auto& am : ATTRIBUTE_MAPPINGS)
auto iFind = attribs.find(am.mType);
if(iFind != attribs.end())
{
- DALI_ASSERT_DEBUG(iFind->second->mBufferView->mBuffer->mUri.compare(meshDef.mUri) == 0);
- auto& accessor = meshDef.*(am.mAccessor);
+ DALI_ASSERT_DEBUG(iFind->second->mBufferView->mBuffer->mUri.compare(meshDefinition.mUri) == 0);
+ auto& accessor = meshDefinition.*(am.mAccessor);
accessor = ConvertMeshPrimitiveAccessor(*iFind->second);
if(iFind->first == gt::Attribute::JOINTS_0)
{
- meshDef.mFlags |= (iFind->second->mComponentType == gt::Component::UNSIGNED_SHORT) * MeshDefinition::U16_JOINT_IDS;
- DALI_ASSERT_DEBUG(MaskMatch(meshDef.mFlags, MeshDefinition::U16_JOINT_IDS) || iFind->second->mComponentType == gt::Component::FLOAT);
+ meshDefinition.mFlags |= (iFind->second->mComponentType == gt::Component::UNSIGNED_SHORT) * MeshDefinition::U16_JOINT_IDS;
+ DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U16_JOINT_IDS) || iFind->second->mComponentType == gt::Component::FLOAT);
}
}
else if(needNormalsTangents)
switch(am.mType)
{
case gt::Attribute::NORMAL:
- meshDef.RequestNormals();
+ meshDefinition.RequestNormals();
break;
case gt::Attribute::TANGENT:
- meshDef.RequestTangents();
+ meshDefinition.RequestTangents();
break;
default:
}
}
- if(p.mIndices)
+ if(primitive.mIndices)
{
- meshDef.mIndices = ConvertMeshPrimitiveAccessor(*p.mIndices);
- meshDef.mFlags |= (p.mIndices->mComponentType == gt::Component::UNSIGNED_INT) * MeshDefinition::U32_INDICES;
- DALI_ASSERT_DEBUG(MaskMatch(meshDef.mFlags, MeshDefinition::U32_INDICES) || p.mIndices->mComponentType == gt::Component::UNSIGNED_SHORT);
+ meshDefinition.mIndices = ConvertMeshPrimitiveAccessor(*primitive.mIndices);
+ meshDefinition.mFlags |= (primitive.mIndices->mComponentType == gt::Component::UNSIGNED_INT) * MeshDefinition::U32_INDICES;
+ DALI_ASSERT_DEBUG(MaskMatch(meshDefinition.mFlags, MeshDefinition::U32_INDICES) || primitive.mIndices->mComponentType == gt::Component::UNSIGNED_SHORT);
}
- if(!p.mTargets.empty())
+ if(!primitive.mTargets.empty())
{
- meshDef.mBlendShapes.reserve(p.mTargets.size());
- meshDef.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
- for(const auto& target : p.mTargets)
+ meshDefinition.mBlendShapes.reserve(primitive.mTargets.size());
+ meshDefinition.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
+ for(const auto& target : primitive.mTargets)
{
MeshDefinition::BlendShape blendShape;
blendShape.tangents = ConvertMeshPrimitiveAccessor(*it->second);
}
- if(!m.mWeights.empty())
+ if(!mesh.mWeights.empty())
{
- blendShape.weight = m.mWeights[meshDef.mBlendShapes.size()];
+ blendShape.weight = mesh.mWeights[meshDefinition.mBlendShapes.size()];
}
- meshDef.mBlendShapes.push_back(std::move(blendShape));
+ meshDefinition.mBlendShapes.push_back(std::move(blendShape));
}
}
- outMeshes.push_back({std::move(meshDef), MeshGeometry{}});
+ outMeshes.push_back({std::move(meshDefinition), MeshGeometry{}});
}
}
}
-ModelNode* MakeModelNode(const gt::Mesh::Primitive& prim, ConversionContext& cctx)
+ModelRenderable* MakeModelRenderable(const gt::Mesh::Primitive& prim, ConversionContext& context)
{
- auto modelNode = new ModelNode();
+ auto modelRenderable = new ModelRenderable();
- modelNode->mShaderIdx = 0; // TODO: further thought
+ modelRenderable->mShaderIdx = 0; // TODO: further thought
auto materialIdx = prim.mMaterial.GetIndex();
if(INVALID_INDEX == materialIdx)
{
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#default-material
- if(INVALID_INDEX == cctx.mDefaultMaterial)
+ if(INVALID_INDEX == context.mDefaultMaterial)
{
- auto& outMaterials = cctx.mOutput.mResources.mMaterials;
- cctx.mDefaultMaterial = outMaterials.size();
+ auto& outMaterials = context.mOutput.mResources.mMaterials;
+ context.mDefaultMaterial = outMaterials.size();
ConvertMaterial(gt::Material{}, outMaterials);
}
- materialIdx = cctx.mDefaultMaterial;
+ materialIdx = context.mDefaultMaterial;
}
- modelNode->mMaterialIdx = materialIdx;
+ modelRenderable->mMaterialIdx = materialIdx;
- return modelNode;
+ return modelRenderable;
}
void ConvertCamera(const gt::Camera& camera, CameraParameters& camParams)
}
}
-void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& cctx, bool isMRendererModel)
+void ConvertNode(gt::Node const& node, const Index gltfIdx, Index parentIdx, ConversionContext& context, bool isMRendererModel)
{
- auto& output = cctx.mOutput;
+ auto& output = context.mOutput;
auto& scene = output.mScene;
auto& resources = output.mResources;
ExceptionFlinger(ASSERT_LOCATION) << "Node name '" << node.mName << "' is not unique; scene is invalid.";
}
- cctx.mNodeIndices.RegisterMapping(gltfIdx, idx);
+ context.mNodeIndices.RegisterMapping(gltfIdx, idx);
Index skeletonIdx = node.mSkin ? node.mSkin.GetIndex() : INVALID_INDEX;
- if(node.mMesh && !node.mMesh->mPrimitives.empty())
+ if(node.mMesh)
{
- auto& mesh = *node.mMesh;
-
- auto iPrim = mesh.mPrimitives.begin();
- auto modelNode = MakeModelNode(*iPrim, cctx);
- auto meshIdx = cctx.mMeshIds[node.mMesh.GetIndex()];
- modelNode->mMeshIdx = meshIdx;
-
- weakNode->mRenderable.reset(modelNode);
-
- DALI_ASSERT_DEBUG(resources.mMeshes[meshIdx].first.mSkeletonIdx == INVALID_INDEX ||
- resources.mMeshes[meshIdx].first.mSkeletonIdx == skeletonIdx);
- resources.mMeshes[meshIdx].first.mSkeletonIdx = skeletonIdx;
-
- // As does model-exporter, we'll create anonymous child nodes for additional mesh( primitiv)es.
- while(++iPrim != mesh.mPrimitives.end())
+ auto& mesh = *node.mMesh;
+ uint32_t primitiveCount = mesh.mPrimitives.size();
+ auto meshIdx = context.mMeshIds[node.mMesh.GetIndex()];
+ weakNode->mRenderables.reserve(primitiveCount);
+ for(uint32_t i = 0; i < primitiveCount; ++i)
{
- std::unique_ptr<NodeDefinition> child{new NodeDefinition};
- child->mParentIdx = idx;
-
- auto childModel = MakeModelNode(*iPrim, cctx);
-
- ++meshIdx;
- childModel->mMeshIdx = meshIdx;
+ std::unique_ptr<NodeDefinition::Renderable> renderable;
+ auto modelRenderable = MakeModelRenderable(mesh.mPrimitives[i], context);
+ modelRenderable->mMeshIdx = meshIdx + i;
- child->mRenderable.reset(childModel);
+ DALI_ASSERT_DEBUG(resources.mMeshes[modelRenderable->mMeshIdx].first.mSkeletonIdx == INVALID_INDEX ||
+ resources.mMeshes[modelRenderable->mMeshIdx].first.mSkeletonIdx == skeletonIdx);
+ resources.mMeshes[modelRenderable->mMeshIdx].first.mSkeletonIdx = skeletonIdx;
- scene.AddNode(std::move(child));
-
- DALI_ASSERT_DEBUG(resources.mMeshes[meshIdx].first.mSkeletonIdx == INVALID_INDEX ||
- resources.mMeshes[meshIdx].first.mSkeletonIdx == skeletonIdx);
- resources.mMeshes[meshIdx].first.mSkeletonIdx = skeletonIdx;
+ renderable.reset(modelRenderable);
+ weakNode->mRenderables.push_back(std::move(renderable));
}
}
for(auto& n : node.mChildren)
{
- ConvertNode(*n, n.GetIndex(), idx, cctx, isMRendererModel);
+ ConvertNode(*n, n.GetIndex(), idx, context, isMRendererModel);
}
}
-void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& cctx, bool isMRendererModel)
+void ConvertSceneNodes(const gt::Scene& scene, ConversionContext& context, bool isMRendererModel)
{
- auto& outScene = cctx.mOutput.mScene;
+ auto& outScene = context.mOutput.mScene;
Index rootIdx = outScene.GetNodeCount();
switch(scene.mNodes.size())
{
break;
case 1:
- ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, cctx, isMRendererModel);
+ ConvertNode(*scene.mNodes[0], scene.mNodes[0].GetIndex(), INVALID_INDEX, context, isMRendererModel);
outScene.AddRootNode(rootIdx);
break;
for(auto& n : scene.mNodes)
{
- ConvertNode(*n, n.GetIndex(), rootIdx, cctx, isMRendererModel);
+ ConvertNode(*n, n.GetIndex(), rootIdx, context, isMRendererModel);
}
break;
}
}
}
-void ConvertNodes(const gt::Document& doc, ConversionContext& cctx, bool isMRendererModel)
+void ConvertNodes(const gt::Document& doc, ConversionContext& context, bool isMRendererModel)
{
- ConvertSceneNodes(*doc.mScene, cctx, isMRendererModel);
+ ConvertSceneNodes(*doc.mScene, context, isMRendererModel);
for(uint32_t i = 0, i1 = doc.mScene.GetIndex(); i < i1; ++i)
{
- ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel);
+ ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel);
}
for(uint32_t i = doc.mScene.GetIndex() + 1; i < doc.mScenes.size(); ++i)
{
- ConvertSceneNodes(doc.mScenes[i], cctx, isMRendererModel);
+ ConvertSceneNodes(doc.mScenes[i], context, isMRendererModel);
}
}
return duration;
}
-void ConvertAnimations(const gt::Document& doc, ConversionContext& cctx)
+void ConvertAnimations(const gt::Document& doc, ConversionContext& context)
{
- auto& output = cctx.mOutput;
+ auto& output = context.mOutput;
output.mAnimationDefinitions.reserve(output.mAnimationDefinitions.size() + doc.mAnimations.size());
}
else
{
- Index index = cctx.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex());
- nodeName = cctx.mOutput.mScene.GetNode(index)->mName;
+ Index index = context.mNodeIndices.GetRuntimeId(channel.mTarget.mNode.GetIndex());
+ nodeName = context.mOutput.mScene.GetNode(index)->mName;
}
float duration = 0.f;
animatedProperty.mPropertyName = POSITION_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Vector3>(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
+ duration = LoadKeyFrames<Vector3>(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
animatedProperty.mTimePeriod = {0.f, duration};
break;
animatedProperty.mPropertyName = ORIENTATION_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Quaternion>(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
+ duration = LoadKeyFrames<Quaternion>(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
animatedProperty.mTimePeriod = {0.f, duration};
break;
animatedProperty.mPropertyName = SCALE_PROPERTY;
animatedProperty.mKeyFrames = KeyFrames::New();
- duration = LoadKeyFrames<Vector3>(cctx.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
+ duration = LoadKeyFrames<Vector3>(context.mPath, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
animatedProperty.mTimePeriod = {0.f, duration};
break;
}
case gt::Animation::Channel::Target::WEIGHTS:
{
- duration = LoadBlendShapeKeyFrames(cctx.mPath, channel, nodeName, propertyIndex, animationDef.mProperties);
+ duration = LoadBlendShapeKeyFrames(context.mPath, channel, nodeName, propertyIndex, animationDef.mProperties);
break;
}
}
}
-void ProcessSkins(const gt::Document& doc, ConversionContext& cctx)
+void ProcessSkins(const gt::Document& doc, ConversionContext& context)
{
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skininversebindmatrices
// If an inverseBindMatrices accessor was provided, we'll load the joint data from the buffer,
}
};
- auto& resources = cctx.mOutput.mResources;
+ auto& resources = context.mOutput.mResources;
resources.mSkeletons.reserve(doc.mSkins.size());
for(auto& s : doc.mSkins)
std::unique_ptr<IInverseBindMatrixProvider> ibmProvider;
if(s.mInverseBindMatrices)
{
- ibmProvider.reset(new InverseBindMatrixAccessor(*s.mInverseBindMatrices, cctx.mPath));
+ ibmProvider.reset(new InverseBindMatrixAccessor(*s.mInverseBindMatrices, context.mPath));
}
else
{
SkeletonDefinition skeleton;
if(s.mSkeleton.GetIndex() != INVALID_INDEX)
{
- skeleton.mRootNodeIdx = cctx.mNodeIndices.GetRuntimeId(s.mSkeleton.GetIndex());
+ skeleton.mRootNodeIdx = context.mNodeIndices.GetRuntimeId(s.mSkeleton.GetIndex());
}
skeleton.mJoints.resize(s.mJoints.size());
auto iJoint = skeleton.mJoints.begin();
for(auto& j : s.mJoints)
{
- iJoint->mNodeIdx = cctx.mNodeIndices.GetRuntimeId(j.GetIndex());
+ iJoint->mNodeIdx = context.mNodeIndices.GetRuntimeId(j.GetIndex());
ibmProvider->Provide(iJoint->mInverseBindMatrix);
void ProduceShaders(ShaderDefinitionFactory& shaderFactory, SceneDefinition& scene)
{
- for(size_t i0 = 0, i1 = scene.GetNodeCount(); i0 != i1; ++i0)
+ uint32_t nodeCount = scene.GetNodeCount();
+ for(uint32_t i = 0; i < nodeCount; ++i)
{
- auto nodeDef = scene.GetNode(i0);
- if(auto renderable = nodeDef->mRenderable.get())
+ auto nodeDef = scene.GetNode(i);
+ for(auto& renderable : nodeDef->mRenderables)
{
- renderable->mShaderIdx = shaderFactory.ProduceShader(*nodeDef);
+ if(shaderFactory.ProduceShader(*renderable) == INVALID_INDEX)
+ {
+ DALI_LOG_ERROR("Fail to produce shader\n");
+ }
}
}
}
js::SetObjectReader(TEXURE_READER);
js::SetObjectReader(TEXURE_INFO_READER);
js::SetObjectReader(MATERIAL_PBR_READER);
+ js::SetObjectReader(MATERIAL_SPECULAR_READER);
+ js::SetObjectReader(MATERIAL_IOR_READER);
+ js::SetObjectReader(MATERIAL_EXTENSION_READER);
js::SetObjectReader(MATERIAL_READER);
js::SetObjectReader(MESH_PRIMITIVE_READER);
js::SetObjectReader(MESH_READER);
js::SetObjectReader(SCENE_READER);
}
-void SetDefaultEnvironmentMap(const gt::Document& doc, ConversionContext& cctx)
+void SetDefaultEnvironmentMap(const gt::Document& doc, ConversionContext& context)
{
EnvironmentDefinition envDef;
envDef.mUseBrdfTexture = true;
envDef.mIblIntensity = Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
- cctx.mOutput.mResources.mEnvironmentMaps.push_back({std::move(envDef), EnvironmentDefinition::Textures()});
+ context.mOutput.mResources.mEnvironmentMaps.push_back({std::move(envDef), EnvironmentDefinition::Textures()});
}
} // namespace
DOCUMENT_READER.Read(rootObj, doc);
auto path = url.substr(0, url.rfind('/') + 1);
- ConversionContext cctx{params, path, INVALID_INDEX};
+ ConversionContext context{params, path, INVALID_INDEX};
- ConvertMaterials(doc, cctx);
- ConvertMeshes(doc, cctx);
- ConvertNodes(doc, cctx, isMRendererModel);
- ConvertAnimations(doc, cctx);
- ProcessSkins(doc, cctx);
+ ConvertMaterials(doc, context);
+ ConvertMeshes(doc, context);
+ ConvertNodes(doc, context, isMRendererModel);
+ ConvertAnimations(doc, context);
+ ProcessSkins(doc, context);
ProduceShaders(shaderFactory, params.mScene);
params.mScene.EnsureUniqueSkinningShaderInstances(params.mResources);
// Set Default Environment map
- SetDefaultEnvironmentMap(doc, cctx);
+ SetDefaultEnvironmentMap(doc, context);
}
} // namespace Loader
++iTexture;
}
+ if(checkStage(SPECULAR))
+ {
+ raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+ ++iTexture;
+ }
+
+ if(checkStage(SPECULAR_COLOR))
+ {
+ raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+ ++iTexture;
+ }
+
return raw;
}
enum Flags : uint32_t
{
// Texture semantics
- ALBEDO = NthBit(0),
- METALLIC = NthBit(1),
- ROUGHNESS = NthBit(2),
- NORMAL = NthBit(3),
- EMISSIVE = NthBit(4), // TODO: support
- OCCLUSION = NthBit(5), // TODO: support
- SUBSURFACE = NthBit(6), // Note: dli-only
+ ALBEDO = NthBit(0),
+ METALLIC = NthBit(1),
+ ROUGHNESS = NthBit(2),
+ NORMAL = NthBit(3),
+ EMISSIVE = NthBit(4),
+ OCCLUSION = NthBit(5),
+ SPECULAR = NthBit(6),
+ SPECULAR_COLOR = NthBit(7),
+ SUBSURFACE = NthBit(8), // Note: dli-only
// Other binary options
TRANSPARENCY = NthBit(20),
public: // DATA
uint32_t mFlags = 0x0;
- Index mEnvironmentIdx = 0;
- Vector4 mColor = Color::WHITE;
- float mMetallic = 1.f;
- float mRoughness = 1.f;
- Vector4 mBaseColorFactor = Vector4::ONE;
- float mNormalScale = 1.f;
- float mOcclusionStrength = 1.f;
- Vector3 mEmissiveFactor = Vector3::ZERO;
+ Index mEnvironmentIdx = 0;
+ Vector4 mColor = Color::WHITE;
+ float mMetallic = 1.f;
+ float mRoughness = 1.f;
+ Vector4 mBaseColorFactor = Vector4::ONE;
+ float mNormalScale = 1.f;
+ float mOcclusionStrength = 1.f;
+ Vector3 mEmissiveFactor = Vector3::ZERO;
+ float mDielectricSpecular = 0.04f;
+ float mSpecularFactor = 1.0f;
+ Vector3 mSpecularColorFactor = Vector3::ONE;
// For the glTF, each of albedo, metallicRoughness, normal textures are not essential.
bool mNeedAlbedoTexture = true;
bool mNeedMetallicRoughnessTexture = true;
bool mNeedNormalTexture = true;
+ bool mDoubleSided = false;
std::vector<TextureStage> mTextureStages;
};
actor.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY);
- if(mRenderable)
+ for(auto& renderable : mRenderables)
{
- mRenderable->OnCreate(*this, params, actor);
+ renderable->OnCreate(*this, params, actor);
}
for(auto& e : mExtras)
bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
{
- if(mRenderable)
+ if(mRenderables.empty())
{
- if(!mRenderable->GetExtents(resources, min, max))
+ return false;
+ }
+
+ bool useModelExtents = false;
+ for(auto& renderable : mRenderables)
+ {
+ Vector3 renderableMin(Vector3::ONE * MAXFLOAT), renderableMax(-Vector3::ONE * MAXFLOAT);
+ if(!renderable->GetExtents(resources, renderableMin, renderableMax))
{
- // If the renderable node don't have mesh accessor, use size to compute extents.
- min = -mSize / 2.0f;
- max = mSize / 2.0f;
+ useModelExtents = false;
+ break;
}
- return true;
+ useModelExtents = true;
+ min.x = std::min(min.x, renderableMin.x);
+ min.y = std::min(min.y, renderableMin.y);
+ min.z = std::min(min.z, renderableMin.z);
+ max.x = std::max(max.x, renderableMax.x);
+ max.y = std::max(max.y, renderableMax.y);
+ max.z = std::max(max.z, renderableMax.z);
}
- return false;
+ if(!useModelExtents)
+ {
+ // If the renderable node don't have mesh accessor, use size to compute extents.
+ min = -mSize / 2.0f;
+ max = mSize / 2.0f;
+ }
+ return true;
}
-bool ModelNode::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
+bool ModelRenderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
{
auto& mesh = resources.mMeshes[mMeshIdx];
uint32_t minSize = mesh.first.mPositions.mBlob.mMin.size();
return false;
}
-void ModelNode::RegisterResources(IResourceReceiver& receiver) const
+void ModelRenderable::RegisterResources(IResourceReceiver& receiver) const
{
Renderable::RegisterResources(receiver);
receiver.Register(ResourceType::Mesh, mMeshIdx);
receiver.Register(ResourceType::Material, mMaterialIdx);
}
-void ModelNode::ReflectResources(IResourceReflector& reflector)
+void ModelRenderable::ReflectResources(IResourceReflector& reflector)
{
Renderable::ReflectResources(reflector);
reflector.Reflect(ResourceType::Mesh, mMeshIdx);
reflector.Reflect(ResourceType::Material, mMaterialIdx);
}
-void ModelNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
+void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
{
DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
Renderable::OnCreate(node, params, actor);
auto& resources = params.mResources;
auto& mesh = resources.mMeshes[mMeshIdx];
- auto renderer = actor.GetRendererAt(0);
+ auto renderer = actor.GetRendererAt(actor.GetRendererCount() - 1u);
Geometry geometry = mesh.second.geometry;
renderer.SetGeometry(geometry);
textures = newTextureSet;
}
- renderer.SetTextures(textures);
-
- actor.SetProperty(Actor::Property::COLOR, mColor);
-
- actor.RegisterProperty("uHasVertexColor", static_cast<float>(mesh.first.mColors.IsDefined()));
+ renderer.RegisterProperty("uHasVertexColor", static_cast<float>(mesh.first.mColors.IsDefined()));
auto& matDef = resources.mMaterials[mMaterialIdx].first;
actor.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
actor.RegisterProperty("uMetallicFactor", matDef.mMetallic);
actor.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
+ actor.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
+ actor.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
+ actor.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
actor.RegisterProperty("uNormalScale", matDef.mNormalScale);
if(matDef.mFlags & MaterialDefinition::OCCLUSION)
{
- actor.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
+ renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
}
if(matDef.mFlags & MaterialDefinition::EMISSIVE)
{
- actor.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
+ renderer.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
}
Index envIdx = matDef.mEnvironmentIdx;
- actor.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
- actor.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection);
+ renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
+ renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection);
float opaque = 0.0f;
float mask = 0.0f;
mask = 1.0f;
}
}
- actor.RegisterProperty("uOpaque", opaque);
- actor.RegisterProperty("uMask", mask);
- actor.RegisterProperty("uAlphaThreshold", alphaCutoff);
+ renderer.RegisterProperty("uOpaque", opaque);
+ renderer.RegisterProperty("uMask", mask);
+ renderer.RegisterProperty("uAlphaThreshold", alphaCutoff);
+
+ renderer.SetTextures(textures);
+
+ actor.SetProperty(Actor::Property::COLOR, mColor);
}
-void ArcNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
+void ArcRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
{
- ModelNode::OnCreate(node, params, actor);
+ ModelRenderable::OnCreate(node, params, actor);
actor.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0);
actor.RegisterProperty("arcCaps", mArcCaps);
actor.RegisterProperty("endAngle", endPolar);
}
-void ArcNode::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector)
+void ArcRenderable::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector)
{
float endAngle = 0.f;
if(diffAngle <= 0.001f)
{
- //0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N
+ // 0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N
endAngle = startAngle + 0.001f;
}
else if(diffAngle >= 360.f)
bool mIsVisible = true;
- std::unique_ptr<Renderable> mRenderable;
+ std::vector<std::unique_ptr<Renderable>> mRenderables;
std::unique_ptr<CustomizationDefinition> mCustomization;
std::vector<Extra> mExtras;
std::vector<ConstraintDefinition> mConstraints;
Index mParentIdx = INVALID_INDEX;
};
-class DALI_SCENE3D_API ModelNode : public NodeDefinition::Renderable
+class DALI_SCENE3D_API ModelRenderable : public NodeDefinition::Renderable
{
public: // DATA
Vector4 mColor = Color::WHITE;
/**
* @brief Parameters for an Arc node.
*/
-class DALI_SCENE3D_API ArcNode : public ModelNode
+class DALI_SCENE3D_API ArcRenderable : public ModelRenderable
{
public: // DATA
bool mAntiAliasing = true;
} // namespace Scene3D
} // namespace Dali
-#endif //DALI_SCENE3D_LOADER_NODE_DEFINITION_H_
+#endif // DALI_SCENE3D_LOADER_NODE_DEFINITION_H_
void Start(const NodeDefinition& n)
{
- if(n.mRenderable)
+ for(auto& renderable : n.mRenderables)
{
- n.mRenderable->RegisterResources(counter);
+ renderable->RegisterResources(counter);
}
}
NodeDefinition* SceneDefinition::AddNode(std::unique_ptr<NodeDefinition>&& nodeDef)
{
- if(FindNode(nodeDef->mName))
+ if(!nodeDef->mName.empty() && FindNode(nodeDef->mName))
{
return nullptr;
}
std::map<Index, std::map<Index, std::vector<Index*>>> skinningShaderUsers;
for(auto& node : mNodes)
{
- if(node->mRenderable)
+ for(auto& renderable : node->mRenderables)
{
ResourceReflector reflector;
- node->mRenderable->ReflectResources(reflector);
+ renderable->ReflectResources(reflector);
if(reflector.iMesh)
{
SortAndDeduplicateSkinningRequests(requests);
- for(auto& i : requests)
+ for(auto& request : requests)
{
- auto& skeleton = resources.mSkeletons[i.mSkeletonIdx];
+ auto& skeleton = resources.mSkeletons[request.mSkeletonIdx];
if(skeleton.mJoints.empty())
{
- LOGD(("Skeleton %d has no joints.", i.mSkeletonIdx));
+ LOGD(("Skeleton %d has no joints.", request.mSkeletonIdx));
continue;
}
Index boneIdx = 0;
- for(auto& j : skeleton.mJoints)
+ for(auto& joint : skeleton.mJoints)
{
- auto node = GetNode(j.mNodeIdx);
+ auto node = GetNode(joint.mNodeIdx);
Actor actor = rootActor.FindChildByName(node->mName);
- ConfigureBoneMatrix(j.mInverseBindMatrix, actor, i.mShader, boneIdx);
+ ConfigureBoneMatrix(joint.mInverseBindMatrix, actor, request.mShader, boneIdx);
}
}
}
std::map<Index, std::map<std::string, std::vector<Index*>>> blendShapeShaderUsers;
for(auto& node : mNodes)
{
- if(node->mRenderable)
+ for(auto& renderable : node->mRenderables)
{
ResourceReflector reflector;
- node->mRenderable->ReflectResources(reflector);
+ renderable->ReflectResources(reflector);
if(reflector.iMesh)
{
}
}
-uint64_t HashNode(const NodeDefinition& nodeDef, const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
+uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
{
Hash hash;
hash.Add("SSS");
}
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+ {
+ hash.Add("SPECTEX");
+ }
+
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+ {
+ hash.Add("SPECCOLTEX");
+ }
+
if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
{
hash.Add("OCCL" /*USION*/);
mImpl->mShaderMap.clear();
}
-Index ShaderDefinitionFactory::ProduceShader(const NodeDefinition& nodeDef)
+Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& renderable)
{
- DALI_ASSERT_DEBUG(nodeDef.mRenderable);
+ auto& resources = *mImpl->mResources;
- auto& resources = *mImpl->mResources;
ResourceReceiver receiver{resources};
- nodeDef.mRenderable->RegisterResources(receiver);
+ renderable.RegisterResources(receiver);
+
if(!(receiver.mMeshDef && receiver.mMaterialDef))
{
+ renderable.mShaderIdx = INVALID_INDEX;
return INVALID_INDEX;
}
auto& shaderMap = mImpl->mShaderMap;
- uint64_t hash = HashNode(nodeDef, *receiver.mMaterialDef, *receiver.mMeshDef);
+ uint64_t hash = HashNode(*receiver.mMaterialDef, *receiver.mMeshDef);
auto iFind = shaderMap.find(hash);
if(iFind != shaderMap.end())
{
- return iFind->second;
- }
-
- ShaderDefinition shaderDef;
- shaderDef.mUseBuiltInShader = true;
- shaderDef.mRendererState = RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK;
-
- auto& materialDef = *receiver.mMaterialDef;
- const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
- if(hasTransparency)
- {
- // TODO: this requires more granularity
- shaderDef.mRendererState = (shaderDef.mRendererState | RendererState::ALPHA_BLEND) & ~RendererState::DEPTH_WRITE;
+ renderable.mShaderIdx = iFind->second;
}
-
- if(hasTransparency ||
- !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) ||
- !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
-
+ else
{
- shaderDef.mDefines.push_back("THREE_TEX");
+ ShaderDefinition shaderDef;
+ shaderDef.mUseBuiltInShader = true;
+ shaderDef.mRendererState = RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE;
- // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential.
- if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO))
+ auto& materialDef = *receiver.mMaterialDef;
+ if(!materialDef.mDoubleSided)
{
- shaderDef.mDefines.push_back("BASECOLOR_TEX");
+ shaderDef.mRendererState |= RendererState::CULL_BACK;
}
- if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
+ const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
+ if(hasTransparency)
{
- shaderDef.mDefines.push_back("METALLIC_ROUGHNESS_TEX");
+ // TODO: this requires more granularity
+ shaderDef.mRendererState = (shaderDef.mRendererState | RendererState::ALPHA_BLEND) & ~RendererState::DEPTH_WRITE;
}
- if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL))
+ if(hasTransparency ||
+ !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) ||
+ !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
+
{
- shaderDef.mDefines.push_back("NORMAL_TEX");
- }
- }
+ shaderDef.mDefines.push_back("THREE_TEX");
- if(materialDef.GetAlphaCutoff() > 0.f)
- {
- shaderDef.mDefines.push_back("ALPHA_TEST");
- }
+ // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential.
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO))
+ {
+ shaderDef.mDefines.push_back("BASECOLOR_TEX");
+ }
- if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE))
- {
- shaderDef.mDefines.push_back("SSS");
- }
+ if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
+ {
+ shaderDef.mDefines.push_back("METALLIC_ROUGHNESS_TEX");
+ }
- if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
- {
- shaderDef.mDefines.push_back("OCCLUSION");
- }
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL))
+ {
+ shaderDef.mDefines.push_back("NORMAL_TEX");
+ }
+ }
- if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
- {
- shaderDef.mDefines.push_back("EMISSIVE");
- }
+ if(materialDef.GetAlphaCutoff() > 0.f)
+ {
+ shaderDef.mDefines.push_back("ALPHA_TEST");
+ }
- if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
- {
- shaderDef.mDefines.push_back("GLTF_CHANNELS");
- }
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE))
+ {
+ shaderDef.mDefines.push_back("SSS");
+ }
- const auto& meshDef = *receiver.mMeshDef;
- if(meshDef.IsSkinned())
- {
- shaderDef.mDefines.push_back("SKINNING");
- }
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+ {
+ shaderDef.mDefines.push_back("MATERIAL_SPECULAR_TEXTURE");
+ }
- if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
- {
- shaderDef.mDefines.push_back("FLIP_V");
- }
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+ {
+ shaderDef.mDefines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE");
+ }
- if(meshDef.HasBlendShapes())
- {
- bool hasPositions = false;
- bool hasNormals = false;
- bool hasTangents = false;
- RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents);
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
+ {
+ shaderDef.mDefines.push_back("OCCLUSION");
+ }
- if(hasPositions)
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
{
- shaderDef.mDefines.push_back("MORPH_POSITION");
+ shaderDef.mDefines.push_back("EMISSIVE");
}
- if(hasNormals)
+ if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
{
- shaderDef.mDefines.push_back("MORPH_NORMAL");
+ shaderDef.mDefines.push_back("GLTF_CHANNELS");
}
- if(hasTangents)
+ const auto& meshDef = *receiver.mMeshDef;
+ if(meshDef.IsSkinned())
{
- shaderDef.mDefines.push_back("MORPH_TANGENT");
+ shaderDef.mDefines.push_back("SKINNING");
}
- if(hasPositions || hasNormals || hasTangents)
+ if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
{
- shaderDef.mDefines.push_back("MORPH");
+ shaderDef.mDefines.push_back("FLIP_V");
+ }
- if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion)
+ if(meshDef.HasBlendShapes())
+ {
+ bool hasPositions = false;
+ bool hasNormals = false;
+ bool hasTangents = false;
+ RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents);
+
+ if(hasPositions)
{
- shaderDef.mDefines.push_back("MORPH_VERSION_2_0");
+ shaderDef.mDefines.push_back("MORPH_POSITION");
+ }
+
+ if(hasNormals)
+ {
+ shaderDef.mDefines.push_back("MORPH_NORMAL");
+ }
+
+ if(hasTangents)
+ {
+ shaderDef.mDefines.push_back("MORPH_TANGENT");
+ }
+
+ if(hasPositions || hasNormals || hasTangents)
+ {
+ shaderDef.mDefines.push_back("MORPH");
+
+ if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion)
+ {
+ shaderDef.mDefines.push_back("MORPH_VERSION_2_0");
+ }
}
}
- }
- if(meshDef.mTangentType == Property::VECTOR4)
- {
- shaderDef.mDefines.push_back("VEC4_TANGENT");
- }
+ if(meshDef.mTangentType == Property::VECTOR4)
+ {
+ shaderDef.mDefines.push_back("VEC4_TANGENT");
+ }
- shaderDef.mUniforms["uMaxLOD"] = 6.f;
- shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
+ shaderDef.mUniforms["uMaxLOD"] = 6.f;
+ shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
- Index result = resources.mShaders.size();
- shaderMap[hash] = result;
+ Index result = resources.mShaders.size();
+ shaderMap[hash] = result;
- resources.mShaders.emplace_back(std::move(shaderDef), Shader());
+ resources.mShaders.emplace_back(std::move(shaderDef), Shader());
+
+ renderable.mShaderIdx = result;
+ }
- return result;
+ return renderable.mShaderIdx;
}
} // namespace Loader
// INTERNAL INCLUDES
#include "dali-scene3d/public-api/api.h"
#include "dali-scene3d/public-api/loader/index.h"
+#include <dali-scene3d/public-api/loader/node-definition.h>
// EXTERNAL INCLUDER
#include <memory>
* already existing in the ResourceBundle are ignored), otherwise the index of the previously
* created shader will be returned.
*/
- Index ProduceShader(const NodeDefinition& nodeDef);
+ Index ProduceShader(NodeDefinition::Renderable& renderable);
private:
struct Impl;
Size newLayoutSize;
bool isAutoScrollEnabled = false;
bool isAutoScrollMaxTextureExceeded = false;
+ bool isHiddenInputEnabled = false;
layoutEngine.LayoutText(layoutParameters,
newLayoutSize,
textParameters.ellipsisEnabled,
isAutoScrollEnabled,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition);
return newLayoutSize;
#include "async-image-loader-impl.h"
// EXTERNAL INCLUDES
-#include <dali/public-api/adaptor-framework/async-task-manager.h>
#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
namespace Dali
{
uint32_t frameIndex,
DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
{
- LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, preMultiplyOnLoad,MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
+ LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
+ Dali::AsyncTaskManager::Get().AddTask(loadingTask);
+ return mLoadTaskId;
+}
+
+uint32_t AsyncImageLoader::LoadAnimatedImage(Dali::AnimatedImageLoading animatedImageLoading,
+ uint32_t frameIndex,
+ Dali::ImageDimensions desiredSize,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
+ DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
+{
+ LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, desiredSize, fittingMode, samplingMode, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
Dali::AsyncTaskManager::Get().AddTask(loadingTask);
return mLoadTaskId;
}
{
LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, url, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, loadPlanes, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
AsyncTaskManager::Get().AddTask(loadingTask);
- mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask,mLoadTaskId));
+ mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask, mLoadTaskId));
return mLoadTaskId;
}
{
LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, encodedImageBuffer, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
Dali::AsyncTaskManager::Get().AddTask(loadingTask);
- mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask,mLoadTaskId));
+ mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask, mLoadTaskId));
return mLoadTaskId;
}
{
LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad, MakeCallback(this, &AsyncImageLoader::ProcessLoadedImage));
Dali::AsyncTaskManager::Get().AddTask(loadingTask);
- mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask,mLoadTaskId));
+ mLoadingTasks.push_back(AsyncImageLoadingInfo(loadingTask, mLoadTaskId));
return mLoadTaskId;
}
void AsyncImageLoader::RemoveCompletedTask()
{
std::uint32_t loadingTaskId;
- auto end = mLoadingTasks.end();
- auto endCompletedIter = mCompletedTaskIds.end();
+ auto end = mLoadingTasks.end();
+ auto endCompletedIter = mCompletedTaskIds.end();
for(std::vector<AsyncImageLoadingInfo>::iterator iter = mLoadingTasks.begin(); iter != end; ++iter)
{
loadingTaskId = (*iter).loadId;
struct AsyncImageLoadingInfo
{
- AsyncImageLoadingInfo(LoadingTaskPtr loadingTask,std::uint32_t loadId)
+ AsyncImageLoadingInfo(LoadingTaskPtr loadingTask, std::uint32_t loadId)
: loadingTask(loadingTask),
loadId(loadId)
{
DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
/**
+ * @brief Starts an animated image loading task.
+ * @param[in] asyncImageLoader The ayncImageLoader
+ * @param[in] animatedImageLoading The AnimatedImageLoading to load animated image
+ * @param[in] frameIndex The frame index of a frame to be loaded frame
+ * @param[in] dimensions The width and height to fit the loaded image to
+ * @param[in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter
+ * @param[in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size
+ * @param[in] preMultiplyOnLoad ON if the image color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
+ * @return The loading task id
+ */
+ uint32_t LoadAnimatedImage(Dali::AnimatedImageLoading animatedImageLoading,
+ uint32_t frameIndex,
+ Dali::ImageDimensions desiredSize,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
+ DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+
+ /**
* @brief Starts an image loading task.
* @param[in] url The URL of the image file to load
* @param[in] dimensions The width and height to fit the loaded image to
id(id),
textureId(TextureManagerType::INVALID_TEXTURE_ID),
dimensions(),
- fittingMode(),
- samplingMode(),
+ fittingMode(FittingMode::SCALE_TO_FILL),
+ samplingMode(SamplingMode::BOX_THEN_LINEAR),
+ preMultiplyOnLoad(preMultiplyOnLoad),
+ maskPixelBuffer(),
+ contentScale(1.0f),
+ animatedImageLoading(animatedImageLoading),
+ frameIndex(frameIndex),
+ orientationCorrection(),
+ isMaskTask(false),
+ cropToMask(false),
+ loadPlanes(false),
+ isReady(true)
+{
+}
+
+LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, CallbackBase* callback)
+: AsyncTask(callback),
+ url(),
+ encodedImageBuffer(),
+ id(id),
+ textureId(TextureManagerType::INVALID_TEXTURE_ID),
+ dimensions(dimensions),
+ fittingMode(fittingMode),
+ samplingMode(samplingMode),
preMultiplyOnLoad(preMultiplyOnLoad),
maskPixelBuffer(),
contentScale(1.0f),
Devel::PixelBuffer pixelBuffer;
if(animatedImageLoading)
{
- pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
+ pixelBuffer = animatedImageLoading.LoadFrame(frameIndex, dimensions, fittingMode, samplingMode);
}
else if(encodedImageBuffer)
{
// EXTERNAL INCLUDES
#include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
+#include <dali-toolkit/internal/texture-manager/texture-manager-type.h>
#include <dali-toolkit/internal/visuals/visual-url.h>
-#include <dali/public-api/adaptor-framework/async-task-manager.h>
#include <dali/devel-api/adaptor-framework/event-thread-callback.h>
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
#include <dali/devel-api/threading/conditional-wait.h>
#include <dali/devel-api/threading/mutex.h>
#include <dali/devel-api/threading/thread.h>
#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
+#include <dali/public-api/adaptor-framework/async-task-manager.h>
#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
#include <dali/public-api/common/dali-vector.h>
#include <dali/public-api/images/image-operations.h>
#include <dali/public-api/object/ref-object.h>
-#include <dali-toolkit/internal/texture-manager/texture-manager-type.h>
namespace Dali
{
{
namespace Internal
{
-
class LoadingTask;
using LoadingTaskPtr = IntrusivePtr<LoadingTask>;
/**
* Constructor.
* @param [in] id of the task
+ * @param [in] animatedImageLoading The AnimatedImageLoading to load animated image
+ * @param [in] frameIndex The frame index of a frame to be loaded frame
+ * @param [in] dimensions The width and height to fit the loaded image to
+ * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter
+ * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size
+ * @param [in] preMultiplyOnLoad ON if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
+ * @param [in] callback The callback that is called when the operation is completed.
+ */
+ LoadingTask(uint32_t id,
+ Dali::AnimatedImageLoading animatedImageLoading,
+ uint32_t frameIndex,
+ Dali::ImageDimensions dimensions,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
+ DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+ CallbackBase* callback);
+
+ /**
+ * Constructor.
+ * @param [in] id of the task
* @param [in] url The URL of the image file to load.
* @param [in] size The width and height to fit the loaded image to, 0.0 means whole image
* @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
bool isMaskTask : 1; ///< whether this task is for mask or not
bool cropToMask : 1; ///< Whether to crop the content to the mask size
bool loadPlanes : 1; ///< Whether to load image planes
- bool isReady : 1; ///< Whether this task ready to run
+ bool isReady : 1; ///< Whether this task ready to run
};
} // namespace Internal
Vector<Character>& srcCharacters = impl.mModel->mLogicalModel->mText;
Vector<Character> displayCharacters;
bool useHiddenText = false;
- if(impl.mHiddenInput && impl.mEventData != nullptr && !impl.mEventData->mIsShowingPlaceholderText)
+ if(impl.mHiddenInput && impl.mEventData != nullptr)
{
- impl.mHiddenInput->Substitute(srcCharacters, displayCharacters);
- useHiddenText = true;
+ if(impl.mEventData->mIsShowingPlaceholderText)
+ {
+ impl.mHiddenInput->InitPreviousTextCount();
+ }
+ else
+ {
+ impl.mHiddenInput->Substitute(srcCharacters, displayCharacters, impl.mEventData->mPrimaryCursorPosition);
+ useHiddenText = true;
+ }
}
Vector<Character>& utf32Characters = useHiddenText ? displayCharacters : srcCharacters;
// Update the visual model.
bool isAutoScrollEnabled = impl.mIsAutoScrollEnabled;
bool isAutoScrollMaxTextureExceeded = impl.mIsAutoScrollMaxTextureExceeded;
+ bool isHiddenInputEnabled = false;
+ if(impl.mHiddenInput && impl.mEventData != nullptr && impl.mHiddenInput->GetHideMode() != Toolkit::HiddenInput::Mode::HIDE_NONE)
+ {
+ isHiddenInputEnabled = true;
+ }
Size newLayoutSize;
viewUpdated = impl.mLayoutEngine.LayoutText(layoutParameters,
elideTextEnabled,
isAutoScrollEnabled,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition);
impl.mIsAutoScrollEnabled = isAutoScrollEnabled;
mSubstituteText(STAR),
mDisplayDuration(DEFAULT_SHOW_DURATION),
mSubstituteCount(0),
- mPreviousTextCount(0)
+ mPreviousTextCount(0u),
+ mIsLastCharacterShow(false)
{
mTimer = Timer::New(mDisplayDuration);
mTimer.TickSignal().Connect(this, &HiddenText::OnTick);
map[Toolkit::HiddenInput::Property::SHOW_LAST_CHARACTER_DURATION] = mDisplayDuration;
}
-void HiddenText::Substitute(const Vector<Character>& source, Vector<Character>& destination)
+void HiddenText::Substitute(const Vector<Character>& source, Vector<Character>& destination, Length cursorPos)
{
const Length characterCount = source.Count();
}
case Toolkit::HiddenInput::Mode::SHOW_LAST_CHARACTER:
{
+ hideStart = begin;
+ hideEnd = end;
if(mPreviousTextCount < characterCount)
{
- hideStart = begin;
- hideEnd = end - 1;
if(mDisplayDuration > 0)
{
mTimer.SetInterval(mDisplayDuration);
mTimer.Start();
+ mIsLastCharacterShow = true;
}
else
{
}
else
{
- hideStart = begin;
- hideEnd = end;
+ mIsLastCharacterShow = false;
}
break;
}
}
- for(; begin < end; ++begin)
+
+
+ if(mHideMode == Toolkit::HiddenInput::Mode::SHOW_LAST_CHARACTER)
{
- if(begin >= hideStart && begin < hideEnd)
+ Length currentPos = 0u;
+ for(; begin < end; ++begin)
{
- *begin = static_cast<uint32_t>(mSubstituteText);
+ if(begin >= hideStart && begin < hideEnd && cursorPos > 0u && currentPos != cursorPos - 1u)
+ {
+ *begin = static_cast<uint32_t>(mSubstituteText);
+ }
+ else
+ {
+ *begin = mIsLastCharacterShow ? *sourcePos : static_cast<uint32_t>(mSubstituteText);
+ }
sourcePos++;
+ currentPos++;
}
- else
+ }
+ else
+ {
+ for(; begin < end; ++begin)
{
- *begin = *sourcePos++;
+ if(begin >= hideStart && begin < hideEnd)
+ {
+ *begin = static_cast<uint32_t>(mSubstituteText);
+ sourcePos++;
+ }
+ else
+ {
+ *begin = *sourcePos++;
+ }
}
}
mPreviousTextCount = characterCount;
}
+void HiddenText::InitPreviousTextCount()
+{
+ mPreviousTextCount = 0u;
+}
+
+int HiddenText::GetHideMode()
+{
+ return mHideMode;
+}
+
bool HiddenText::OnTick()
{
if(mObserver != NULL)
{
mObserver->DisplayTimeExpired();
}
-
+ mIsLastCharacterShow = false;
return false;
}
* @param[in] source The original text
* @param[out] destination The applied text
*/
- void Substitute(const Vector<Character>& source, Vector<Character>& destination);
+ void Substitute(const Vector<Character>& source, Vector<Character>& destination, Length currentCursorIndex);
+
+ /**
+ * @brief Initialize the value of PreviousTextCount
+ */
+ void InitPreviousTextCount();
+
+ /**
+ * @brief Returns the hide mode of hidden text.
+ * @return The hide mode of hidden text.
+ */
+ int GetHideMode();
/**
* @brief Invoked when the timer is expired
int mDisplayDuration;
int mSubstituteCount;
Length mPreviousTextCount;
+ bool mIsLastCharacterShow;
};
} // namespace Text
* @param[out] lineLayout The line layout.
* @param[in] completelyFill Whether to completely fill the line ( even if the last word exceeds the boundaries ).
* @param[in] ellipsisPosition Where is the location the text elide
+ * @param[in] hiddenInputEnabled Whether the hidden input is enabled.
*/
void GetLineLayoutForBox(const Parameters& parameters,
LayoutBidiParameters& bidiParameters,
bool completelyFill,
DevelText::EllipsisPosition::Type ellipsisPosition,
bool enforceEllipsisInSingleLine,
- bool elideTextEnabled)
+ bool elideTextEnabled,
+ bool hiddenInputEnabled)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->GetLineLayoutForBox\n");
DALI_LOG_INFO(gLogFilter, Debug::Verbose, " initial glyph index : %d\n", lineLayout.glyphIndex);
const float previousTmpLength = tmpLineLayout.length;
const float previousTmpWhiteSpaceLengthEndOfLine = tmpLineLayout.whiteSpaceLengthEndOfLine;
- if(isWhiteSpace)
+ // The calculated text size is used in atlas renderer.
+ // When the text is all white space, partial render issue occurs because the width is 0.
+ // To avoid issue, do not remove the white space size in hidden input mode.
+ if(isWhiteSpace && !hiddenInputEnabled)
{
// Add the length to the length of white spaces at the end of the line.
tmpLineLayout.whiteSpaceLengthEndOfLine += glyphMetrics.advance;
tmpLineLayout.numberOfGlyphs -= numberOfGLyphsInGroup;
}
- if(isRemovedGlyphWhiteSpace)
+ if(isRemovedGlyphWhiteSpace && !hiddenInputEnabled)
{
tmpLineLayout.penX -= glyphMetrics.advance;
tmpLineLayout.length -= glyphMetrics.advance;
* @param[in] penY The vertical layout position.
* @param[in] currentParagraphDirection The current paragraph's direction.
* @param[in,out] isAutoScrollEnabled If the isAutoScrollEnabled is true and the height of the text exceeds the boundaries of the control the text is elided and the isAutoScrollEnabled is set to false to disable the autoscroll
+ * @param[in] isHiddenInputEnabled Whether the hidden input is enabled.
* @param[in] ellipsisPosition Where is the location the text elide
*
* return Whether the line is ellipsized.
float penY,
bool& isAutoScrollEnabled,
bool isAutoScrollMaxTextureExceeded,
+ bool isHiddenInputEnabled,
DevelText::EllipsisPosition::Type ellipsisPosition,
bool enforceEllipsisInSingleLine)
{
true,
ellipsisPosition,
enforceEllipsisInSingleLine,
- true);
+ true,
+ isHiddenInputEnabled);
if(ellipsisPosition == DevelText::EllipsisPosition::START && !isMultiline)
{
bool elideTextEnabled,
bool& isAutoScrollEnabled,
bool isAutoScrollMaxTextureExceeded,
+ bool isHiddenInputEnabled,
DevelText::EllipsisPosition::Type ellipsisPosition)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->LayoutText\n");
false,
ellipsisPosition,
false,
- elideTextEnabled);
+ elideTextEnabled,
+ isHiddenInputEnabled);
DALI_LOG_INFO(gLogFilter, Debug::Verbose, " glyph index %d\n", layout.glyphIndex);
DALI_LOG_INFO(gLogFilter, Debug::Verbose, " character index %d\n", layout.characterIndex);
penY,
isAutoScrollEnabled,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition,
false);
}
penY,
isAutoScrollEnabled,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition,
true);
}
bool elideTextEnabled,
bool& isAutoScrollEnabled,
bool isAutoScrollMaxTextureExceeded,
+ bool isHiddenInputEnabled,
DevelText::EllipsisPosition::Type ellipsisPosition)
{
return mImpl->LayoutText(layoutParameters,
elideTextEnabled,
isAutoScrollEnabled,
isAutoScrollMaxTextureExceeded,
+ isHiddenInputEnabled,
ellipsisPosition);
}
* @param[in] elideTextEnabled Whether the text elide is enabled.
* @param[in,out] isAutoScrollEnabled If the isAutoScrollEnabled is true and the height of the text exceeds the boundaries of the control the text is elided and the isAutoScrollEnabled is set to false to disable the autoscroll
* @param[in] isAutoScrollMaxTextureExceeded If isAutoScrollMaxTextureExceeded is true, enable ellipsis during auro scroll.
+ * @param[in] isHiddenInputEnabled if isHiddenInputEnabled is true, hidden input feature is enabled.
* @param[in] ellipsisPosition The location of the text ellipsis
*
* @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character.
bool elideTextEnabled,
bool& isAutoScrollEnabled,
bool isAutoScrollMaxTextureExceeded,
+ bool isHiddenInputEnabled,
DevelText::EllipsisPosition::Type ellipsisPosition);
/**
void TextureAsyncLoadingHelper::LoadAnimatedImage(const TextureManager::TextureId& textureId,
Dali::AnimatedImageLoading animatedImageLoading,
const std::uint32_t& frameIndex,
+ const Dali::ImageDimensions& desiredSize,
+ const Dali::FittingMode::Type& fittingMode,
+ const Dali::SamplingMode::Type& samplingMode,
const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad)
{
- LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, preMultiplyOnLoad, MakeCallback(this, &TextureAsyncLoadingHelper::AsyncLoadComplete));
+ LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, animatedImageLoading, frameIndex, desiredSize, fittingMode, samplingMode, preMultiplyOnLoad, MakeCallback(this, &TextureAsyncLoadingHelper::AsyncLoadComplete));
loadingTask->SetTextureId(textureId);
Dali::AsyncTaskManager::Get().AddTask(loadingTask);
}
const bool& cropToMask,
const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad)
{
-
LoadingTaskPtr loadingTask = new LoadingTask(++mLoadTaskId, pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad, MakeCallback(this, &TextureAsyncLoadingHelper::AsyncLoadComplete));
loadingTask->SetTextureId(textureId);
Dali::AsyncTaskManager::Get().AddTask(loadingTask);
{
namespace Internal
{
-
/**
* @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container
*/
* @param[in] textureId TextureId to reference the texture that will be loaded
* @param[in] animatedImageLoading The AnimatedImageLoading to load animated image
* @param[in] frameIndex The frame index of a frame to be loaded frame
+ * @param[in] desiredSize The size the image is likely to appear at.
+ * This can be set to 0,0 for automatic
+ * @param[in] fittingMode The FittingMode to use
+ * @param[in] samplingMode The SamplingMode to use
* @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
*/
void LoadAnimatedImage(const TextureManager::TextureId& textureId,
Dali::AnimatedImageLoading animatedImageLoading,
const std::uint32_t& frameIndex,
+ const Dali::ImageDimensions& desiredSize,
+ const Dali::FittingMode::Type& fittingMode,
+ const Dali::SamplingMode::Type& samplingMode,
const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad);
/**
namespace
{
-constexpr auto INITIAL_HASH_NUMBER = size_t{0u};
+constexpr auto INITIAL_HASH_NUMBER = size_t{0u};
constexpr auto TEXTURE_INDEX = 0u; ///< The Index for texture
constexpr auto MASK_TEXTURE_INDEX = 1u; ///< The Index for mask texture
const uint32_t& frameIndex,
TextureManager::TextureId& textureId,
MaskingDataPointer& maskInfo,
+ const Dali::ImageDimensions& desiredSize,
+ const Dali::FittingMode::Type& fittingMode,
const Dali::SamplingMode::Type& samplingMode,
const bool& synchronousLoading,
TextureUploadObserver* textureObserver,
Devel::PixelBuffer pixelBuffer;
if(animatedImageLoading)
{
- pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
+ pixelBuffer = animatedImageLoading.LoadFrame(frameIndex, desiredSize, fittingMode, samplingMode);
}
if(!pixelBuffer)
{
Texture maskTexture;
if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
{
- Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
+ Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile(maskInfo->mAlphaMaskUrl.GetUrl(), desiredSize, fittingMode, samplingMode, true);
if(maskPixelBuffer)
{
if(!maskInfo->mPreappliedMasking)
}
}
- textureId = RequestLoadInternal(url, alphaMaskId, contentScaleFactor, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, UseAtlas::NO_ATLAS, cropToMask, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad, animatedImageLoading, frameIndex, false);
+ textureId = RequestLoadInternal(url, alphaMaskId, contentScaleFactor, desiredSize, fittingMode, samplingMode, UseAtlas::NO_ATLAS, cropToMask, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad, animatedImageLoading, frameIndex, false);
TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId);
if(loadState == TextureManager::LoadState::UPLOADED)
textureInfo.loadState = LoadState::LOADING;
if(!textureInfo.loadSynchronously)
{
- auto premultiplyOnLoad = (textureInfo.preMultiplyOnLoad && textureInfo.maskTextureId == INVALID_TEXTURE_ID) ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
+ auto premultiplyOnLoad = (textureInfo.preMultiplyOnLoad && textureInfo.maskTextureId == INVALID_TEXTURE_ID) ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
if(textureInfo.animatedImageLoading)
{
- mAsyncLoader->LoadAnimatedImage(textureInfo.textureId, textureInfo.animatedImageLoading, textureInfo.frameIndex, premultiplyOnLoad);
+ mAsyncLoader->LoadAnimatedImage(textureInfo.textureId, textureInfo.animatedImageLoading, textureInfo.frameIndex, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, premultiplyOnLoad);
}
else
{
DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::ApplyMask(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F");
- textureInfo.loadState = LoadState::MASK_APPLYING;
+ textureInfo.loadState = LoadState::MASK_APPLYING;
auto premultiplyOnLoad = textureInfo.preMultiplyOnLoad ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
mAsyncLoader->ApplyMask(textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask, premultiplyOnLoad);
}
#include <dali/devel-api/adaptor-framework/animated-image-loading.h>
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
+#include <dali/public-api/adaptor-framework/round-robin-container-view.h>
#include <dali/public-api/common/dali-vector.h>
#include <dali/public-api/rendering/geometry.h>
-#include <dali/public-api/adaptor-framework/round-robin-container-view.h>
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
* @param[in] frameIndex The frame index to load.
* @param[out] textureId The textureId of the frame
* @param[in, out] maskInfo Mask info structure
+ * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0, 0 for automatic
+ * @param[in] fittingMode The FittingMode to use
* @param[in] samplingMode The SamplingMode to use
* @param[in] synchronousLoading true if the frame should be loaded synchronously
* @param[in] textureObserver The client object should inherit from this and provide the "LoadCompleted" virtual.
const uint32_t& frameIndex,
TextureManager::TextureId& textureId,
MaskingDataPointer& maskInfo,
+ const Dali::ImageDimensions& desiredSize,
+ const Dali::FittingMode::Type& fittingMode,
const Dali::SamplingMode::Type& samplingMode,
const bool& synchronousLoading,
TextureUploadObserver* textureObserver,
*/
void EmitLoadComplete(TextureUploadObserver* observer, TextureManager::TextureInfo& textureInfo, const bool& success);
-
/**
* @brief Remove observer in textureInfo
*
*/
void ObserverDestroyed(TextureUploadObserver* observer);
-private: // Member Variables:
- TextureCacheManager mTextureCacheManager; ///< Manager the life-cycle and caching of Textures
- std::unique_ptr<TextureAsyncLoadingHelper> mAsyncLoader; ///< The Asynchronous image loader used to provide all local async loads
- Dali::Vector<LifecycleObserver*> mLifecycleObservers; ///< Lifecycle observers of texture manager
- Dali::Vector<QueueElement> mLoadQueue; ///< Queue of textures to load after NotifyObservers
- Dali::Vector<QueueElement> mRemoveQueue; ///< Queue of textures to remove after NotifyObservers
- TextureManager::TextureId mLoadingQueueTextureId; ///< TextureId when it is loading. it causes Load Textures to be queued.
- bool mLoadYuvPlanes; ///< A global flag to specify if the image should be loaded as yuv planes
+private: // Member Variables:
+ TextureCacheManager mTextureCacheManager; ///< Manager the life-cycle and caching of Textures
+ std::unique_ptr<TextureAsyncLoadingHelper> mAsyncLoader; ///< The Asynchronous image loader used to provide all local async loads
+ Dali::Vector<LifecycleObserver*> mLifecycleObservers; ///< Lifecycle observers of texture manager
+ Dali::Vector<QueueElement> mLoadQueue; ///< Queue of textures to load after NotifyObservers
+ Dali::Vector<QueueElement> mRemoveQueue; ///< Queue of textures to remove after NotifyObservers
+ TextureManager::TextureId mLoadingQueueTextureId; ///< TextureId when it is loading. it causes Load Textures to be queued.
+ bool mLoadYuvPlanes; ///< A global flag to specify if the image should be loaded as yuv planes
};
} // namespace Internal
{
const int CUSTOM_PROPERTY_COUNT(5); // ltr, wrap, pixel area, crop to mask, mask texture ratio
+// fitting modes
+DALI_ENUM_TO_STRING_TABLE_BEGIN(FITTING_MODE)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, SHRINK_TO_FIT)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, SCALE_TO_FILL)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, FIT_WIDTH)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, FIT_HEIGHT)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, DEFAULT)
+DALI_ENUM_TO_STRING_TABLE_END(FITTING_MODE)
+
+// sampling modes
+DALI_ENUM_TO_STRING_TABLE_BEGIN(SAMPLING_MODE)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::SamplingMode, BOX)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::SamplingMode, NEAREST)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::SamplingMode, LINEAR)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::SamplingMode, BOX_THEN_NEAREST)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::SamplingMode, BOX_THEN_LINEAR)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::SamplingMode, NO_FILTER)
+ DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::SamplingMode, DONT_CARE)
+DALI_ENUM_TO_STRING_TABLE_END(SAMPLING_MODE)
+
// stop behavior
DALI_ENUM_TO_STRING_TABLE_BEGIN(STOP_BEHAVIOR)
DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::DevelImageVisual::StopBehavior, CURRENT_FRAME)
AnimatedImageVisualPtr AnimatedImageVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties)
{
- AnimatedImageVisualPtr visual(new AnimatedImageVisual(factoryCache, shaderFactory));
+ AnimatedImageVisualPtr visual(new AnimatedImageVisual(factoryCache, shaderFactory, ImageDimensions()));
visual->InitializeAnimatedImage(imageUrl);
visual->SetProperties(properties);
AnimatedImageVisualPtr AnimatedImageVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Property::Array& imageUrls, const Property::Map& properties)
{
- AnimatedImageVisualPtr visual(new AnimatedImageVisual(factoryCache, shaderFactory));
+ AnimatedImageVisualPtr visual(new AnimatedImageVisual(factoryCache, shaderFactory, ImageDimensions()));
visual->mImageUrls = new ImageCache::UrlList();
visual->mImageUrls->reserve(imageUrls.Count());
return visual;
}
-AnimatedImageVisualPtr AnimatedImageVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl)
+AnimatedImageVisualPtr AnimatedImageVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, ImageDimensions size)
{
- AnimatedImageVisualPtr visual(new AnimatedImageVisual(factoryCache, shaderFactory));
+ AnimatedImageVisualPtr visual(new AnimatedImageVisual(factoryCache, shaderFactory, size));
visual->InitializeAnimatedImage(imageUrl);
visual->Initialize();
if(mAnimatedImageLoading)
{
- mImageCache = new RollingAnimatedImageCache(textureManager, mAnimatedImageLoading, mMaskingData, *this, mCacheSize, mBatchSize, mWrapModeU, mWrapModeV, IsSynchronousLoadingRequired(), mFactoryCache.GetPreMultiplyOnLoad());
+ mImageCache = new RollingAnimatedImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, mAnimatedImageLoading, mMaskingData, *this, mCacheSize, mBatchSize, mWrapModeU, mWrapModeV, IsSynchronousLoadingRequired(), mFactoryCache.GetPreMultiplyOnLoad());
}
else if(mImageUrls)
{
uint16_t cacheSize = std::max(std::min(std::max(batchSize, mCacheSize), numUrls), MINIMUM_CACHESIZE);
if(cacheSize < numUrls)
{
- mImageCache = new RollingImageCache(textureManager, *mImageUrls, mMaskingData, *this, cacheSize, batchSize, mFrameDelay);
+ mImageCache = new RollingImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, *mImageUrls, mMaskingData, *this, cacheSize, batchSize, mFrameDelay);
}
else
{
- mImageCache = new FixedImageCache(textureManager, *mImageUrls, mMaskingData, *this, batchSize, mFrameDelay);
+ mImageCache = new FixedImageCache(textureManager, mDesiredSize, mFittingMode, mSamplingMode, *mImageUrls, mMaskingData, *this, batchSize, mFrameDelay);
}
}
}
}
-AnimatedImageVisual::AnimatedImageVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory)
+AnimatedImageVisual::AnimatedImageVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, ImageDimensions desiredSize)
: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::ANIMATED_IMAGE),
mFrameDelayTimer(),
mPlacementActor(),
mLoadPolicy(Toolkit::ImageVisual::LoadPolicy::ATTACHED),
mReleasePolicy(Toolkit::ImageVisual::ReleasePolicy::DETACHED),
mMaskingData(),
+ mDesiredSize(desiredSize),
mFrameCount(0),
mImageSize(),
mActionStatus(DevelAnimatedImageVisual::Action::PLAY),
mWrapModeU(WrapMode::DEFAULT),
mWrapModeV(WrapMode::DEFAULT),
+ mFittingMode(FittingMode::SCALE_TO_FILL),
+ mSamplingMode(SamplingMode::BOX_THEN_LINEAR),
mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
mStartFirstFrame(false),
mIsJumpTo(false)
void AnimatedImageVisual::GetNaturalSize(Vector2& naturalSize)
{
+ if(mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0)
+ {
+ naturalSize.x = mDesiredSize.GetWidth();
+ naturalSize.y = mDesiredSize.GetHeight();
+ return;
+ }
+
+ naturalSize = Vector2::ZERO;
if(mImageSize.GetWidth() == 0 && mImageSize.GetHeight() == 0)
{
if(mMaskingData && mMaskingData->mAlphaMaskUrl.IsValid() &&
map.Insert(Toolkit::ImageVisual::Property::LOAD_POLICY, mLoadPolicy);
map.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy);
+ map.Insert(Toolkit::ImageVisual::Property::FITTING_MODE, mFittingMode);
+ map.Insert(Toolkit::ImageVisual::Property::SAMPLING_MODE, mSamplingMode);
+ map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth());
+ map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight());
}
void AnimatedImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
{
- // Do nothing
+ map.Clear();
+ map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::ANIMATED_IMAGE);
+ if(mImageUrl.IsValid())
+ {
+ map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth());
+ map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight());
+ }
}
void AnimatedImageVisual::OnDoAction(const Dali::Property::Index actionId, const Dali::Property::Value& attributes)
{
DoSetProperty(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, keyValue.second);
}
+ else if(keyValue.first == IMAGE_FITTING_MODE)
+ {
+ DoSetProperty(Toolkit::ImageVisual::Property::FITTING_MODE, keyValue.second);
+ }
+ else if(keyValue.first == IMAGE_SAMPLING_MODE)
+ {
+ DoSetProperty(Toolkit::ImageVisual::Property::SAMPLING_MODE, keyValue.second);
+ }
+ else if(keyValue.first == IMAGE_DESIRED_WIDTH)
+ {
+ DoSetProperty(Toolkit::ImageVisual::Property::DESIRED_WIDTH, keyValue.second);
+ }
+ else if(keyValue.first == IMAGE_DESIRED_HEIGHT)
+ {
+ DoSetProperty(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, keyValue.second);
+ }
}
}
// Load image immediately if LOAD_POLICY requires it
mLoadPolicy = Toolkit::ImageVisual::LoadPolicy::Type(loadPolicy);
break;
}
+
+ case Toolkit::ImageVisual::Property::FITTING_MODE:
+ {
+ int fittingMode = 0;
+ Scripting::GetEnumerationProperty(value, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, fittingMode);
+ mFittingMode = Dali::FittingMode::Type(fittingMode);
+ break;
+ }
+
+ case Toolkit::ImageVisual::Property::SAMPLING_MODE:
+ {
+ int samplingMode = 0;
+ Scripting::GetEnumerationProperty(value, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, samplingMode);
+ mSamplingMode = Dali::SamplingMode::Type(samplingMode);
+ break;
+ }
+
+ case Toolkit::ImageVisual::Property::DESIRED_WIDTH:
+ {
+ float desiredWidth = 0.0f;
+ if(value.Get(desiredWidth))
+ {
+ mDesiredSize.SetWidth(desiredWidth);
+ }
+ else
+ {
+ DALI_LOG_ERROR("AnimatedImageVisual: desiredWidth property has incorrect type\n");
+ }
+ break;
+ }
+
+ case Toolkit::ImageVisual::Property::DESIRED_HEIGHT:
+ {
+ float desiredHeight = 0.0f;
+ if(value.Get(desiredHeight))
+ {
+ mDesiredSize.SetHeight(desiredHeight);
+ }
+ else
+ {
+ DALI_LOG_ERROR("AnimatedImageVisual: desiredHeight property has incorrect type\n");
+ }
+ break;
+ }
}
}
#define DALI_TOOLKIT_INTERNAL_ANIMATED_IMAGE_VISUAL_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
* @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
* @param[in] shaderFactory The ImageVisualShaderFactory object
* @param[in] imageUrl The URL to animated image resource to use
+ * @param[in] size The width and height of the image. The visual size will be used if these are 0.
*/
- static AnimatedImageVisualPtr New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl);
+ static AnimatedImageVisualPtr New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, ImageDimensions size = ImageDimensions());
public: // from Visual
/**
*
* @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
* @param[in] shaderFactory The ImageVisualShaderFactory object
+ * @param[in] desiredSize The width and height of the image. The visual size will be used if these are 0.
*/
- AnimatedImageVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory);
+ AnimatedImageVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, ImageDimensions desiredSize);
/**
* @brief A reference counted object may only be deleted by calling Unreference().
Dali::Toolkit::ImageVisual::LoadPolicy::Type mLoadPolicy;
Dali::Toolkit::ImageVisual::ReleasePolicy::Type mReleasePolicy;
TextureManager::MaskingDataPointer mMaskingData;
+ Dali::ImageDimensions mDesiredSize;
// Shared variables
uint32_t mFrameCount; // Number of frames
DevelAnimatedImageVisual::Action::Type mActionStatus;
- Dali::WrapMode::Type mWrapModeU : 3;
- Dali::WrapMode::Type mWrapModeV : 3;
- DevelImageVisual::StopBehavior::Type mStopBehavior : 2;
- bool mStartFirstFrame : 1;
- bool mIsJumpTo : 1;
+ Dali::WrapMode::Type mWrapModeU : 3;
+ Dali::WrapMode::Type mWrapModeV : 3;
+ Dali::FittingMode::Type mFittingMode : 3;
+ Dali::SamplingMode::Type mSamplingMode : 4;
+ DevelImageVisual::StopBehavior::Type mStopBehavior : 2;
+ bool mStartFirstFrame : 1;
+ bool mIsJumpTo : 1;
};
} // namespace Internal
} // namespace
FixedImageCache::FixedImageCache(TextureManager& textureManager,
+ ImageDimensions size,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
UrlList& urlList,
TextureManager::MaskingDataPointer& maskingData,
ImageCache::FrameReadyObserver& observer,
uint32_t batchSize,
uint32_t interval)
-: ImageCache(textureManager, maskingData, observer, batchSize, interval),
+: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, interval),
mImageUrls(urlList),
mFront(FIRST_FRAME_INDEX)
{
Dali::ImageDimensions textureRectSize;
auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
- mTextureManager.LoadTexture(url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, mMaskingData, synchronousLoading, mImageUrls[frameIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
+ mTextureManager.LoadTexture(url, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mImageUrls[frameIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
mRequestingLoad = false;
}
}
/**
* Constructor.
* @param[in] textureManager The texture manager
+ * @param[in] size The width and height to fit the loaded image to.
+ * @param[in] fittingMode The FittingMode of the resource to load
+ * @param[in] samplingMode The SamplingMode of the resource to load
* @param[in] urlList List of urls to cache
* @param[in] maskingData Masking data to be applied.
* @param[in] observer FrameReady observer
* batch and cache sizes. The cache is as large as the number of urls.
*/
FixedImageCache(TextureManager& textureManager,
+ ImageDimensions size,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
UrlList& urlList,
TextureManager::MaskingDataPointer& maskingData,
ImageCache::FrameReadyObserver& observer,
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * 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.
namespace Internal
{
ImageCache::ImageCache(TextureManager& textureManager,
+ ImageDimensions size,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
TextureManager::MaskingDataPointer& maskingData,
ImageCache::FrameReadyObserver& observer,
uint32_t batchSize,
: mTextureManager(textureManager),
mObserver(observer),
mMaskingData(maskingData),
+ mDesiredSize(size),
+ mFittingMode(fittingMode),
+ mSamplingMode(samplingMode),
mBatchSize(batchSize),
mInterval(interval),
mLoadState(TextureManager::LoadState::NOT_STARTED),
/**
* @brief Constructor.
* @param[in] textureManager The texture manager
- * @param[in] urlList List of urls to cache
- * @param[in] observer FrameReady observer
+ * @param[in] size The width and height to fit the loaded image to.
+ * @param[in] fittingMode The FittingMode of the resource to load
+ * @param[in] samplingMode The SamplingMode of the resource to load
+ * @param[in] observer FrameReady observer
* @param[in] maskingData Masking data to be applied.
* @param[in] batchSize The size of a batch to load
* @param[in] interval Time interval(ms) between each frame
* batch and cache sizes. The cache is as large as the number of urls.
*/
ImageCache(TextureManager& textureManager,
+ ImageDimensions size,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
TextureManager::MaskingDataPointer& maskingData,
ImageCache::FrameReadyObserver& observer,
uint32_t batchSize,
TextureManager& mTextureManager;
FrameReadyObserver& mObserver;
TextureManager::MaskingDataPointer& mMaskingData;
+ Dali::ImageDimensions mDesiredSize;
+ Dali::FittingMode::Type mFittingMode : 3;
+ Dali::SamplingMode::Type mSamplingMode : 4;
uint32_t mBatchSize;
uint32_t mInterval;
TextureManager::LoadState mLoadState;
} // namespace
RollingAnimatedImageCache::RollingAnimatedImageCache(TextureManager& textureManager,
+ ImageDimensions size,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
AnimatedImageLoading& animatedImageLoading,
TextureManager::MaskingDataPointer& maskingData,
ImageCache::FrameReadyObserver& observer,
const Dali::WrapMode::Type& wrapModeV,
bool isSynchronousLoading,
bool preMultiplyOnLoad)
-: ImageCache(textureManager, maskingData, observer, batchSize, 0u),
+: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, 0u),
mImageUrl(animatedImageLoading.GetUrl()),
mAnimatedImageLoading(animatedImageLoading),
mFrameCount(SINGLE_IMAGE_COUNT),
frameIndex,
loadTextureId,
mMaskingData,
- SamplingMode::BOX_THEN_LINEAR,
+ mDesiredSize,
+ mFittingMode,
+ mSamplingMode,
synchronousLoading,
this,
preMultiplyOnLoading);
{
DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "RollingAnimatedImageCache::GetFrontTextureSet() FrameNumber:%d\n", mQueue[0].mFrameNumber);
- TextureManager::TextureId textureId = GetCachedTextureId(0);
- TextureSet textureSet = mTextureManager.GetTextureSet(textureId);
+ TextureManager::TextureId textureId = GetCachedTextureId(0);
+ TextureSet textureSet = mTextureManager.GetTextureSet(textureId);
if(textureSet)
{
Sampler sampler = Sampler::New();
/**
* @brief Constructor.
* @param[in] textureManager The texture manager
- * @param[in] animatedImageLoading The loaded animated image
+ * @param[in] size The width and height to fit the loaded image to.
+ * @param[in] fittingMode The FittingMode of the resource to load
+ * @param[in] samplingMode The SamplingMode of the resource to load
+ * @param[in] animatedImageLoading The loaded animated image
* @param[in] maskingData Masking data to be applied.
* @param[in] observer FrameReady observer
* @param[in] cacheSize The size of the cache
* batch and cache sizes.
*/
RollingAnimatedImageCache(TextureManager& textureManager,
+ ImageDimensions size,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
AnimatedImageLoading& animatedImageLoading,
TextureManager::MaskingDataPointer& maskingData,
ImageCache::FrameReadyObserver& observer,
namespace Internal
{
RollingImageCache::RollingImageCache(TextureManager& textureManager,
+ ImageDimensions size,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
UrlList& urlList,
TextureManager::MaskingDataPointer& maskingData,
ImageCache::FrameReadyObserver& observer,
uint16_t cacheSize,
uint16_t batchSize,
uint32_t interval)
-: ImageCache(textureManager, maskingData, observer, batchSize, interval),
+: ImageCache(textureManager, size, fittingMode, samplingMode, maskingData, observer, batchSize, interval),
mImageUrls(urlList),
mQueue(cacheSize)
{
TextureManager::TextureId loadTextureId = TextureManager::INVALID_TEXTURE_ID;
TextureSet textureSet = mTextureManager.LoadTexture(
- url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, mMaskingData, synchronousLoading, loadTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
+ url, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, loadTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
mImageUrls[imageFrame.mUrlIndex].mTextureId = loadTextureId;
mRequestingLoad = false;
TextureSet RollingImageCache::GetFrontTextureSet() const
{
- TextureManager::TextureId textureId = GetCachedTextureId(0);
- TextureSet textureSet = mTextureManager.GetTextureSet(textureId);
+ TextureManager::TextureId textureId = GetCachedTextureId(0);
+ TextureSet textureSet = mTextureManager.GetTextureSet(textureId);
if(textureSet)
{
Sampler sampler = Sampler::New();
/**
* Constructor.
* @param[in] textureManager The texture manager
+ * @param[in] size The width and height to fit the loaded image to.
+ * @param[in] fittingMode The FittingMode of the resource to load
+ * @param[in] samplingMode The SamplingMode of the resource to load
* @param[in] urlList List of urls to cache
* @param[in] maskingData Masking data to be applied.
* @param[in] observer FrameReady observer
* batch and cache sizes.
*/
RollingImageCache(TextureManager& textureManager,
+ ImageDimensions size,
+ Dali::FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
UrlList& urlList,
TextureManager::MaskingDataPointer& maskingData,
ImageCache::FrameReadyObserver& observer,
bool mReady = false;
};
- std::vector<UrlStore>& mImageUrls;
- CircularQueue<ImageFrame> mQueue;
+ std::vector<UrlStore>& mImageUrls;
+ CircularQueue<ImageFrame> mQueue;
};
} // namespace Internal
case VisualUrl::GIF:
case VisualUrl::WEBP:
{
- visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
+ visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, size);
break;
}
case VisualUrl::JSON:
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 3;
+const unsigned int TOOLKIT_MICRO_VERSION = 4;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.2.3
+Version: 2.2.4
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT