*/
#include <dali-toolkit-test-suite-utils.h>
+#include <toolkit-event-thread-callback.h>
+#include <toolkit-timer.h>
+
#include <dali-toolkit/dali-toolkit.h>
#include <stdlib.h>
#include <iostream>
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
-#include <toolkit-event-thread-callback.h>
+
using namespace Dali;
using namespace Dali::Toolkit;
END_TEST;
}
+
+namespace
+{
+static bool gCaptureFinishedCalled{false};
+static int32_t gCaptureId{-1};
+static Toolkit::ImageUrl gCapturedImageUrl;
+static Scene3D::SceneView::CaptureFinishState gCaptureFinishState{Scene3D::SceneView::CaptureFinishState::FAILED};
+
+void OnCaptureFinished(Scene3D::SceneView sceneView, Scene3D::SceneView::CaptureResult& captureResult)
+{
+ gCaptureFinishedCalled = true;
+ gCaptureId = captureResult.captureId;
+ gCapturedImageUrl = captureResult.imageUrl;
+ gCaptureFinishState = captureResult.state;
+}
+
+static int32_t gCapturedCount{0};
+static std::vector<int32_t> gCaptureIds;
+static std::vector<Toolkit::ImageUrl> gCapturedImageUrls;
+static std::vector<Scene3D::SceneView::CaptureFinishState> gCaptureFinishStates;
+
+void OnCaptureMultipleFinished(Scene3D::SceneView sceneView, Scene3D::SceneView::CaptureResult& captureResult)
+{
+ gCapturedCount++;
+ gCaptureIds.push_back(captureResult.captureId);
+ gCapturedImageUrls.push_back(captureResult.imageUrl);
+ gCaptureFinishStates.push_back(captureResult.state);
+}
+} // namespace
+
+int UtcDaliSceneViewCapture01(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.CaptureFinishedSignal().Connect(OnCaptureFinished);
+ view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
+
+ application.GetScene().Add(view);
+
+ application.SendNotification();
+ application.Render();
+
+ Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+ view.Add(modelView1);
+
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ CameraActor camera = Dali::CameraActor::New();
+ camera.SetProperty(Dali::Actor::Property::NAME, "camera");
+ camera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ camera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ camera.SetFieldOfView(0.5f);
+ camera.SetNearClippingPlane(1.0f);
+ camera.SetFarClippingPlane(5000.0f);
+ camera.SetProperty(Dali::Actor::Property::POSITION, Vector3(20, 30, 40));
+
+ view.Add(camera);
+
+ gCaptureFinishedCalled = false;
+ gCaptureId = -1;
+ gCapturedImageUrl.Reset();
+ gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
+ int32_t captureId = view.Capture(camera, Vector2(300, 300));
+
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+
+ DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureId, captureId, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCapturedImageUrl.GetUrl().empty(), false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureFinishState, Scene3D::SceneView::CaptureFinishState::SUCCEEDED, TEST_LOCATION);
+
+ Toolkit::ImageUrl tempImageUrl = gCapturedImageUrl;
+
+ gCaptureFinishedCalled = false;
+ gCaptureId = -1;
+ gCapturedImageUrl.Reset();
+ gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
+ int32_t captureId2 = view.Capture(camera, Vector2(400, 400));
+
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+
+ DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
+ DALI_TEST_NOT_EQUALS(captureId, captureId2, 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureId, captureId2, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCapturedImageUrl.GetUrl().empty(), false, TEST_LOCATION);
+ DALI_TEST_NOT_EQUALS(gCapturedImageUrl, tempImageUrl, 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureFinishState, Scene3D::SceneView::CaptureFinishState::SUCCEEDED, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliSceneViewCaptureCancel(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.CaptureFinishedSignal().Connect(OnCaptureFinished);
+ view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
+
+ application.GetScene().Add(view);
+
+ application.SendNotification();
+ application.Render();
+
+ Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+ view.Add(modelView1);
+
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ CameraActor camera = Dali::CameraActor::New();
+ camera.SetProperty(Dali::Actor::Property::NAME, "camera");
+ camera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ camera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ camera.SetFieldOfView(0.5f);
+ camera.SetNearClippingPlane(1.0f);
+ camera.SetFarClippingPlane(5000.0f);
+ camera.SetProperty(Dali::Actor::Property::POSITION, Vector3(20, 30, 40));
+
+ view.Add(camera);
+
+ gCaptureFinishedCalled = false;
+ gCaptureId = -1;
+ gCapturedImageUrl.Reset();
+ gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
+ int32_t captureId = view.Capture(camera, Vector2(300, 300));
+
+ view.Unparent();
+
+ DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureId, captureId, TEST_LOCATION);
+ DALI_TEST_EQUALS(!!gCapturedImageUrl, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureFinishState, Scene3D::SceneView::CaptureFinishState::FAILED, TEST_LOCATION);
+
+
+ gCaptureFinishedCalled = false;
+ gCaptureId = -1;
+ gCapturedImageUrl.Reset();
+ gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
+
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+
+ DALI_TEST_EQUALS(gCaptureFinishedCalled, false, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliSceneViewCaptureFailed(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.CaptureFinishedSignal().Connect(OnCaptureFinished);
+ view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
+
+ application.GetScene().Add(view);
+
+ application.SendNotification();
+ application.Render();
+
+ Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+ view.Add(modelView1);
+
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ CameraActor camera = Dali::CameraActor::New();
+ camera.SetProperty(Dali::Actor::Property::NAME, "camera");
+ camera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ camera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ camera.SetFieldOfView(0.5f);
+ camera.SetNearClippingPlane(1.0f);
+ camera.SetFarClippingPlane(5000.0f);
+ camera.SetProperty(Dali::Actor::Property::POSITION, Vector3(20, 30, 40));
+
+ view.Add(camera);
+
+ gCaptureFinishedCalled = false;
+ gCaptureId = -1;
+ gCapturedImageUrl.Reset();
+ gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
+ int32_t captureId = view.Capture(camera, Vector2(300, 300));
+
+ Test::EmitGlobalTimerSignal();
+ Test::EmitGlobalTimerSignal();
+ Test::EmitGlobalTimerSignal();
+
+ DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureId, captureId, TEST_LOCATION);
+ DALI_TEST_EQUALS(!!gCapturedImageUrl, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureFinishState, Scene3D::SceneView::CaptureFinishState::FAILED, TEST_LOCATION);
+
+ gCaptureFinishedCalled = false;
+ gCaptureId = -1;
+ gCapturedImageUrl.Reset();
+ gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
+
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+
+ DALI_TEST_EQUALS(gCaptureFinishedCalled, false, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliSceneViewCapture02(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.CaptureFinishedSignal().Connect(OnCaptureMultipleFinished);
+ view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
+
+ application.GetScene().Add(view);
+
+ application.SendNotification();
+ application.Render();
+
+ Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+ view.Add(modelView1);
+
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ CameraActor camera = Dali::CameraActor::New();
+ camera.SetProperty(Dali::Actor::Property::NAME, "camera");
+ camera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ camera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ camera.SetFieldOfView(0.5f);
+ camera.SetNearClippingPlane(1.0f);
+ camera.SetFarClippingPlane(5000.0f);
+ camera.SetProperty(Dali::Actor::Property::POSITION, Vector3(20, 30, 40));
+
+ view.Add(camera);
+
+ gCapturedCount = 0;
+ gCaptureIds.clear();
+ gCapturedImageUrls.clear();
+ gCaptureFinishStates.clear();
+ int32_t captureId = view.Capture(camera, Vector2(300, 300));
+ int32_t captureId2 = view.Capture(camera, Vector2(300, 300));
+
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+
+ DALI_TEST_EQUALS(gCapturedCount, 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureIds.size(), 2, TEST_LOCATION);
+ auto idIter1 = std::find(gCaptureIds.begin(), gCaptureIds.end(), captureId);
+ bool isIter1 = idIter1 != gCaptureIds.end();
+ DALI_TEST_EQUALS(isIter1, true, TEST_LOCATION);
+ auto idIter2 = std::find(gCaptureIds.begin(), gCaptureIds.end(), captureId2);
+ bool isIter2 = idIter2 != gCaptureIds.end();
+ DALI_TEST_EQUALS(isIter2, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gCapturedImageUrls.size(), 2, TEST_LOCATION);
+ DALI_TEST_NOT_EQUALS(gCapturedImageUrls[0], gCapturedImageUrls[1], 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureFinishStates[0], Scene3D::SceneView::CaptureFinishState::SUCCEEDED, TEST_LOCATION);
+ DALI_TEST_EQUALS(gCaptureFinishStates[1], Scene3D::SceneView::CaptureFinishState::SUCCEEDED, TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
#include <dali-toolkit/public-api/image-loader/image-url.h>
#include <dali-toolkit/public-api/image-loader/image.h>
#include <dali/devel-api/actors/camera-actor-devel.h>
+#include <dali/devel-api/adaptor-framework/image-loading.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-scene3d/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-scene3d/internal/light/light-impl.h>
-#include <dali/integration-api/debug.h>
-
using namespace Dali;
namespace Dali
// Setup properties, signals and actions using the type-registry.
DALI_TYPE_REGISTRATION_BEGIN(Scene3D::SceneView, Toolkit::Control, Create);
-
DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "AlphaMaskUrl", STRING, ALPHA_MASK_URL)
DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "MaskContentScale", FLOAT, MASK_CONTENT_SCALE)
DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "CropToMask", BOOLEAN, CROP_TO_MASK)
Property::Index RENDERING_BUFFER = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1;
constexpr int32_t DEFAULT_ORIENTATION = 0;
constexpr int32_t INVALID_INDEX = -1;
+constexpr int32_t INVALID_CAPTURE_ID = -1;
constexpr uint32_t MAXIMUM_SIZE_SHADOW_MAP = 2048;
constexpr int32_t SCENE_ORDER_INDEX = 100;
// Compute ViewProjectionMatrix and store it to "tempViewProjectionMatrix" property
auto tempViewProjectionMatrixIndex = shadowLightCamera.RegisterProperty("tempViewProjectionMatrix", Matrix::IDENTITY);
- Constraint projectionMatrixConstraint = Constraint::New<Matrix>(shadowLightCamera, tempViewProjectionMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs) {
+ Constraint projectionMatrixConstraint = Constraint::New<Matrix>(shadowLightCamera, tempViewProjectionMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs)
+ {
Matrix worldMatrix = inputs[0]->GetMatrix();
float tangentFov_2 = tanf(inputs[4]->GetFloat());
float nearDistance = inputs[5]->GetFloat();
projMatrix[14] = -(near + far) / deltaZ;
projMatrix[15] = 1.0f;
- output = output * shadowCameraViewMatrix;
- });
+ output = output * shadowCameraViewMatrix; });
projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::Actor::Property::WORLD_MATRIX});
projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::PROJECTION_MODE});
projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::DevelCameraActor::Property::PROJECTION_DIRECTION});
return;
}
- auto foundLight = std::find_if(mLights.begin(), mLights.end(), [light](std::pair<Scene3D::Light, bool> lightEntity) -> bool { return (lightEntity.second && lightEntity.first == light); });
+ auto foundLight = std::find_if(mLights.begin(), mLights.end(), [light](std::pair<Scene3D::Light, bool> lightEntity) -> bool
+ { return (lightEntity.second && lightEntity.first == light); });
if(foundLight == mLights.end())
{
return mSkyboxOrientation;
}
+int32_t SceneView::Capture(Dali::CameraActor camera, const Vector2& size)
+{
+ if(size.x <= 0.0f || size.y <= 0.0f)
+ {
+ DALI_LOG_ERROR("The width and height should be positive.\n");
+ return INVALID_CAPTURE_ID;
+ }
+
+ uint32_t width = unsigned(size.width);
+ uint32_t height = unsigned(size.height);
+ if(width > Dali::GetMaxTextureSize() || height > Dali::GetMaxTextureSize())
+ {
+ DALI_LOG_ERROR("The input size is too large.\n");
+ return INVALID_CAPTURE_ID;
+ }
+
+ if(!mRootLayer.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
+ {
+ DALI_LOG_ERROR("Current SceneView is not connected on scene tree\n");
+ return INVALID_CAPTURE_ID;
+ }
+
+ if(!camera.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
+ {
+ mRootLayer.Add(camera);
+ }
+
+ std::shared_ptr<CaptureData> captureData = std::make_shared<CaptureData>();
+ captureData->mCaptureId = mCaptureId;
+ captureData->mCaptureTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+ captureData->mCaptureFrameBuffer = Dali::FrameBuffer::New(captureData->mCaptureTexture.GetWidth(), captureData->mCaptureTexture.GetHeight(), Dali::FrameBuffer::Attachment::DEPTH_STENCIL);
+ DevelFrameBuffer::SetMultiSamplingLevel(captureData->mCaptureFrameBuffer, mFrameBufferMultiSamplingLevel);
+ captureData->mCaptureFrameBuffer.AttachColorTexture(captureData->mCaptureTexture);
+
+ RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
+ captureData->mCaptureTask = taskList.CreateTask();
+ captureData->mCaptureTask.SetSourceActor(mRootLayer);
+ captureData->mCaptureTask.SetExclusive(true);
+ captureData->mCaptureTask.SetCullMode(false);
+ captureData->mCaptureTask.SetOrderIndex(SCENE_ORDER_INDEX + 1);
+ captureData->mCaptureTask.SetCameraActor(camera);
+ captureData->mCaptureTask.SetFrameBuffer(captureData->mCaptureFrameBuffer);
+ captureData->mCaptureTask.SetClearEnabled(true);
+ captureData->mCaptureTask.SetClearColor(Color::TRANSPARENT);
+ captureData->mCaptureTask.SetRefreshRate(Dali::RenderTask::REFRESH_ONCE);
+
+ captureData->mCaptureInvertCamera = Dali::CameraActor::New(size);
+ captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::POSITION_X, size.x / 2.0f);
+ captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::POSITION_Y, size.y / 2.0f);
+
+ captureData->mCaptureUrl = Dali::Toolkit::Image::GenerateUrl(captureData->mCaptureFrameBuffer, 0u);
+ captureData->mCaptureImageView = Dali::Toolkit::ImageView::New(captureData->mCaptureUrl.GetUrl());
+ captureData->mCaptureImageView.SetProperty(Dali::Actor::Property::SIZE, size);
+ captureData->mCaptureImageView.Add(captureData->mCaptureInvertCamera);
+
+ Window window = DevelWindow::Get(Self());
+ window.Add(captureData->mCaptureImageView);
+
+ captureData->mCaptureInvertTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+ captureData->mCaptureInvertFrameBuffer = Dali::FrameBuffer::New(captureData->mCaptureInvertTexture.GetWidth(), captureData->mCaptureInvertTexture.GetHeight(), Dali::FrameBuffer::Attachment::DEPTH_STENCIL);
+ captureData->mCaptureInvertFrameBuffer.AttachColorTexture(captureData->mCaptureInvertTexture);
+
+ captureData->mCaptureInvertTask = taskList.CreateTask();
+ captureData->mCaptureInvertTask.SetSourceActor(captureData->mCaptureImageView);
+ captureData->mCaptureInvertTask.SetExclusive(true);
+ captureData->mCaptureInvertTask.SetCullMode(false);
+ captureData->mCaptureInvertTask.SetOrderIndex(SCENE_ORDER_INDEX + 2);
+ captureData->mCaptureInvertTask.SetCameraActor(captureData->mCaptureInvertCamera);
+ captureData->mCaptureInvertTask.SetFrameBuffer(captureData->mCaptureInvertFrameBuffer);
+ captureData->mCaptureInvertTask.SetClearEnabled(true);
+ captureData->mCaptureInvertTask.SetClearColor(Color::TRANSPARENT);
+ captureData->mCaptureInvertTask.SetRefreshRate(Dali::RenderTask::REFRESH_ONCE);
+ captureData->mCaptureInvertTask.FinishedSignal().Connect(this, &SceneView::OnCaptureFinished);
+
+ captureData->mStartTick = mTimerTickCount;
+
+ mCaptureContainer.push_back(std::make_pair(captureData->mCaptureInvertTask, captureData));
+
+ if(!mCaptureTimer)
+ {
+ mCaptureTimer = Dali::Timer::New(1000);
+ mCaptureTimer.TickSignal().Connect(this, &SceneView::OnTimeOut);
+ mCaptureTimer.Start();
+ }
+ return mCaptureId++;
+}
+
+Dali::Scene3D::SceneView::CaptureFinishedSignalType& SceneView::CaptureFinishedSignal()
+{
+ return mCaptureFinishedSignal;
+}
+
Dali::Scene3D::Loader::ShaderManagerPtr SceneView::GetShaderManager() const
{
return mShaderManager;
}
mWindow.Reset();
+ auto self = Self();
+ Dali::Scene3D::SceneView handle(Dali::Scene3D::SceneView::DownCast(self));
+ std::vector<std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>>> tempContainer(mCaptureContainer);
+ for(auto&& capture : tempContainer)
+ {
+ Dali::Scene3D::SceneView::CaptureResult result{capture.second->mCaptureId, Dali::Toolkit::ImageUrl(), Dali::Scene3D::SceneView::CaptureFinishState::FAILED};
+ mCaptureFinishedSignal.Emit(handle, result);
+ }
+ tempContainer.clear();
+
+ for(auto && capture : mCaptureContainer)
+ {
+ if(mSceneHolder)
+ {
+ RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
+ taskList.RemoveTask(capture.second->mCaptureTask);
+ taskList.RemoveTask(capture.second->mCaptureInvertTask);
+ }
+ capture.second->mCaptureTask.Reset();
+ capture.second->mCaptureInvertTask.Reset();
+ capture.second->mCaptureTexture.Reset();
+ capture.second->mCaptureInvertTexture.Reset();
+ capture.second->mCaptureFrameBuffer.Reset();
+ capture.second->mCaptureInvertFrameBuffer.Reset();
+ capture.second->mCaptureUrl.Reset();
+ capture.second->mCaptureImageView.Unparent();
+ capture.second->mCaptureImageView.Reset();
+ capture.second->mCaptureInvertCamera.Unparent();
+ capture.second->mCaptureInvertCamera.Reset();
+ }
+ mCaptureContainer.clear();
+
+
if(mSceneHolder)
{
if(mRenderTask)
}
}
+void SceneView::OnCaptureFinished(Dali::RenderTask& task)
+{
+ int32_t captureId = INVALID_CAPTURE_ID;
+ Dali::Toolkit::ImageUrl imageUrl;
+
+ auto iter = std::find_if(mCaptureContainer.begin(), mCaptureContainer.end(), [task](std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>> item)
+ { return item.first == task; });
+
+ if(iter != mCaptureContainer.end())
+ {
+ captureId = iter->second->mCaptureId;
+ imageUrl = Dali::Toolkit::ImageUrl::New(iter->second->mCaptureInvertTexture);
+ if(mSceneHolder)
+ {
+ RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
+ taskList.RemoveTask(iter->second->mCaptureTask);
+ taskList.RemoveTask(iter->second->mCaptureInvertTask);
+ }
+ iter->second->mCaptureTexture.Reset();
+ iter->second->mCaptureInvertTexture.Reset();
+ iter->second->mCaptureFrameBuffer.Reset();
+ iter->second->mCaptureInvertFrameBuffer.Reset();
+ iter->second->mCaptureUrl.Reset();
+ iter->second->mCaptureImageView.Unparent();
+ iter->second->mCaptureImageView.Reset();
+ mCaptureContainer.erase(iter);
+
+ auto self = Self();
+ Dali::Scene3D::SceneView handle(Dali::Scene3D::SceneView::DownCast(self));
+
+ Dali::Scene3D::SceneView::CaptureResult result{captureId, imageUrl, Dali::Scene3D::SceneView::CaptureFinishState::SUCCEEDED};
+ mCaptureFinishedSignal.Emit(handle, result);
+ }
+
+ if(mCaptureContainer.empty() && mCaptureTimer)
+ {
+ mCaptureTimer.Stop();
+ mCaptureTimer.Reset();
+ mTimerTickCount = 0;
+ }
+}
+
+bool SceneView::OnTimeOut()
+{
+ mTimerTickCount++;
+ auto self = Self();
+ Dali::Scene3D::SceneView handle(Dali::Scene3D::SceneView::DownCast(self));
+ std::vector<std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>>> tempContainer;
+ for(auto&& capture : mCaptureContainer)
+ {
+ if(capture.second->mStartTick + 1 < mTimerTickCount)
+ {
+ tempContainer.push_back(capture);
+ }
+ }
+
+ for(auto&& capture : tempContainer)
+ {
+ Dali::Scene3D::SceneView::CaptureResult result{capture.second->mCaptureId, Dali::Toolkit::ImageUrl(), Dali::Scene3D::SceneView::CaptureFinishState::FAILED};
+ mCaptureFinishedSignal.Emit(handle, result);
+ }
+
+ int32_t tickCount = mTimerTickCount;
+ auto it = std::remove_if(mCaptureContainer.begin(), mCaptureContainer.end(), [tickCount](std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>> item) {
+ return item.second->mStartTick + 1 < tickCount;
+ });
+ mCaptureContainer.erase(it, mCaptureContainer.end());
+ mCaptureContainer.shrink_to_fit();
+
+ if(mCaptureContainer.empty() && mCaptureTimer)
+ {
+ mCaptureTimer.Stop();
+ mCaptureTimer.Reset();
+ mTimerTickCount = 0;
+ }
+
+ return !mCaptureContainer.empty();
+}
+
} // namespace Internal
} // namespace Scene3D
} // namespace Dali
// EXTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/image/image-visual.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
#include <dali/integration-api/adaptor-framework/scene-holder.h>
#include <dali/integration-api/ordered-set.h>
#include <dali/public-api/actors/camera-actor.h>
#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/adaptor-framework/timer.h>
#include <dali/public-api/adaptor-framework/window.h>
#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/capture/capture.h>
#include <dali/public-api/object/weak-handle.h>
#include <dali/public-api/render-tasks/render-task.h>
#include <dali/public-api/rendering/frame-buffer.h>
Quaternion GetSkyboxOrientation() const;
/**
+ * @copydoc SceneView::Capture()
+ */
+ int32_t Capture(Dali::CameraActor camera, const Vector2& size);
+
+ /**
+ * @copydoc SceneView::FinishedSignal
+ */
+ Dali::Scene3D::SceneView::CaptureFinishedSignalType& CaptureFinishedSignal();
+
+ /**
* @brief Retrieves ShaderManager of this SceneView.
* @return ShaderManager of this SceneView.
*/
*/
void UpdateShadowMapBuffer(uint32_t shadowMapSize);
+ /**
+ * @brief CaptureFinished Callback that is called the capture rendering is finished.
+ * @param[in] task RenderTask that draws requested capture scene.
+ */
+ void OnCaptureFinished(Dali::RenderTask& task);
+
+ /**
+ * @brief Time out Callback to handle the case each capture request is not finished for long time.
+ * @return True if the timer needs to go on.
+ */
+ bool OnTimeOut();
+
private:
+ /**
+ * Data to store Capture related objects.
+ */
+ struct CaptureData
+ {
+ int32_t mStartTick;
+ int32_t mCaptureId; // Unique Key to distinguish requested Captures.
+ Dali::Toolkit::ImageUrl mCaptureUrl; // URL for first captured buffer, but it is Y-inverted.
+ Dali::Toolkit::ImageView mCaptureImageView; // ImageView to draw first capture buffer to be transfered as input for invert.
+ Dali::RenderTask mCaptureTask; // RenderTask that is used to capture first buffer.
+ Dali::Texture mCaptureTexture; // First Captured texture, but it is Y-inverted.
+ Dali::FrameBuffer mCaptureFrameBuffer; // First Captured FBO, but it is Y-inverted.
+ Dali::CameraActor mCaptureInvertCamera; // CameraActor to invert first captured buffer by second pass.
+ Dali::RenderTask mCaptureInvertTask; // RenderTask to invert first captured buffer.
+ Dali::Texture mCaptureInvertTexture; // Result texture of second pass. This is final Texture result.
+ Dali::FrameBuffer mCaptureInvertFrameBuffer; // FBO for firnal Texture result
+ };
+
Toolkit::Visual::Base mVisual;
/////////////////////////////////////////////////////////////
// FrameBuffer and Rendertask to render child objects as a 3D Scene
- Dali::WeakHandle<Dali::Window> mWindow;
- Integration::SceneHolder mSceneHolder;
- CameraActor mDefaultCamera;
- CameraActor mSelectedCamera;
- std::vector<CameraActor> mCameras;
- Dali::FrameBuffer mFrameBuffer;
- Dali::Texture mTexture;
- Dali::RenderTask mRenderTask;
- Layer mRootLayer;
- int32_t mWindowOrientation;
- Dali::Actor mSkybox;
- Quaternion mSkyboxOrientation;
- float mSkyboxIntensity{1.0f};
- uint8_t mFrameBufferMultiSamplingLevel{0u};
+ Dali::WeakHandle<Dali::Window> mWindow;
+ Integration::SceneHolder mSceneHolder;
+ CameraActor mDefaultCamera;
+ CameraActor mSelectedCamera;
+ std::vector<CameraActor> mCameras;
+ Dali::FrameBuffer mFrameBuffer;
+ Dali::Texture mTexture;
+ Dali::RenderTask mRenderTask;
+ Layer mRootLayer;
+ int32_t mWindowOrientation;
+ Dali::Actor mSkybox;
+ Quaternion mSkyboxOrientation;
+ float mSkyboxIntensity{1.0f};
+ uint8_t mFrameBufferMultiSamplingLevel{0u};
+ Dali::Scene3D::SceneView::CaptureFinishedSignalType mCaptureFinishedSignal;
+
+ int32_t mCaptureId{0}; // Capture ID for requested capture, this is incrementally increasing.
+ std::vector<std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>>> mCaptureContainer; // Container that stores CaptureData until the Capture is finished.
+ Dali::Timer mCaptureTimer; // Timer to check the capture is time out or not.
+ int32_t mTimerTickCount{0};
Dali::Integration::OrderedSet<Scene3D::Internal::LightObserver, false> mLightObservers; ///< The set of items to be notified when light properties change. (not owned)
return GetImpl(*this).GetSkyboxOrientation();
}
+int32_t SceneView::Capture(Dali::CameraActor camera, const Vector2& size)
+{
+ return GetImpl(*this).Capture(camera, size);
+}
+
+SceneView::CaptureFinishedSignalType& SceneView::CaptureFinishedSignal()
+{
+ return GetImpl(*this).CaptureFinishedSignal();
+}
+
} // namespace Scene3D
} // namespace Dali
// EXTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/public-api/image-loader/image-url.h>
#include <dali/public-api/actors/camera-actor.h>
#include <dali/public-api/common/dali-common.h>
};
};
+ /**
+ * @brief The enumerations used for checking capture success
+ * @SINCE_2_3.25
+ */
+ enum class CaptureFinishState
+ {
+ SUCCEEDED, ///< Succeeded to capture
+ FAILED ///< Failed to capture by time out
+ };
+
public:
+ struct CaptureResult
+ {
+ int32_t captureId;
+ Dali::Toolkit::ImageUrl imageUrl;
+ CaptureFinishState state;
+ };
+
+ /**
+ * @brief Typedef for capture finished signals sent by this class.
+ *
+ * @SINCE_2_3.25
+ */
+ typedef Signal<void(SceneView, CaptureResult&)> CaptureFinishedSignalType;
+
/**
* @brief Create an initialized SceneView.
*
*/
Quaternion GetSkyboxOrientation() const;
+ /**
+ * @brief Requests to capture this SceneView with the Camera.
+ *
+ * @SINCE_2_3.25
+ * @param[in] camera CameraActor to be used for capture.
+ * @param[in] size captured size.
+ * @note The camera is required to be added in this SceneView. (Not need to be a selected camera)
+ * @note If the SceneView is disconnected from Scene, the left capture requests are canceled.
+ * @return capture id that id unique value to distinguish each requiest.
+ */
+ int32_t Capture(Dali::CameraActor camera, const Vector2& size);
+
+ /**
+ * @brief Get capture finished signal.
+ *
+ * @SINCE_2_3.25
+ * @return finished signal instance.
+ */
+ CaptureFinishedSignalType& CaptureFinishedSignal();
+
public: // Not intended for application developers
/// @cond internal
/**