Remove std::vector from public api
[platform/core/uifw/dali-core.git] / dali / internal / event / render-tasks / render-task-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/render-tasks/render-task-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/internal/event/common/event-thread-services.h>
28 #include <dali/internal/event/actors/actor-impl.h>
29 #include <dali/internal/event/actors/camera-actor-impl.h>
30 #include <dali/internal/event/common/property-helper.h>
31 #include <dali/internal/event/common/stage-impl.h>
32 #include <dali/internal/event/images/frame-buffer-image-impl.h>
33 #include <dali/internal/update/nodes/node.h>
34 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
35
36 #if defined(DEBUG_ENABLED)
37 namespace
38 {
39 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
40 }
41 #endif
42
43 namespace Dali
44 {
45
46 namespace Internal
47 {
48
49 namespace // For internal properties
50 {
51
52 // Properties
53
54 //              Name                 Type     writable animatable constraint-input  enum for index-checking
55 DALI_PROPERTY_TABLE_BEGIN
56 DALI_PROPERTY( "viewport-position",  VECTOR2,    true,    true,    true,    Dali::RenderTask::Property::VIEWPORT_POSITION )
57 DALI_PROPERTY( "viewport-size",      VECTOR2,    true,    true,    true,    Dali::RenderTask::Property::VIEWPORT_SIZE     )
58 DALI_PROPERTY( "clear-color",        VECTOR4,    true,    true,    true,    Dali::RenderTask::Property::CLEAR_COLOR       )
59 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
60
61 // Signals
62
63 const char* const SIGNAL_FINISHED = "finished";
64
65 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL );
66
67 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
68
69 } // Unnamed namespace
70
71 RenderTask* RenderTask::New( bool isSystemLevel )
72 {
73   RenderTask* task( new RenderTask( isSystemLevel ) );
74
75   return task;
76 }
77
78 void RenderTask::SetSourceActor( Actor* actor )
79 {
80   mSourceConnector.SetActor( actor );
81 }
82
83 Actor* RenderTask::GetSourceActor() const
84 {
85   return mSourceConnector.mActor;
86 }
87
88 void RenderTask::SetExclusive( bool exclusive )
89 {
90   if ( mExclusive != exclusive )
91   {
92     mExclusive = exclusive;
93
94     if ( mSceneObject )
95     {
96       // mSceneObject is being used in a separate thread; queue a message to set the value
97       SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
98     }
99   }
100 }
101
102 bool RenderTask::IsExclusive() const
103 {
104   return mExclusive;
105 }
106
107 void RenderTask::SetInputEnabled( bool enabled )
108 {
109   mInputEnabled = enabled;
110 }
111
112 bool RenderTask::GetInputEnabled() const
113 {
114   return mInputEnabled;
115 }
116
117 void RenderTask::SetCameraActor( CameraActor* cameraActor )
118 {
119   mCameraConnector.SetActor( cameraActor );
120 }
121
122 CameraActor* RenderTask::GetCameraActor() const
123 {
124   // camera connector can only point to camera actor
125   return static_cast< CameraActor* >( mCameraConnector.mActor );
126 }
127
128 void RenderTask::SetTargetFrameBuffer( Dali::FrameBufferImage image )
129 {
130   if ( mFrameBufferImage != image )
131   {
132     // if we have a scene object we need to track connection status and set frame buffer id as well as updating target frame buffer
133     if ( mSceneObject )
134     {
135       if(mFrameBufferImage)
136       {
137         GetImplementation(mFrameBufferImage).Disconnect();
138       }
139
140       // update target frame buffer
141       mFrameBufferImage = image;
142
143       unsigned int resourceId = 0;
144       if(mFrameBufferImage)
145       {
146         GetImplementation(mFrameBufferImage).Connect();
147
148         resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
149       }
150
151       // mSceneObject is being used in a separate thread; queue a message to set the value
152       SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
153     }
154     else
155     {
156       // update target frame buffer
157       mFrameBufferImage = image;
158     }
159   }
160 }
161
162 Dali::FrameBufferImage RenderTask::GetTargetFrameBuffer() const
163 {
164   return mFrameBufferImage;
165 }
166
167 void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
168 {
169   mScreenToFrameBufferFunction = conversionFunction;
170 }
171
172 RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
173 {
174   return mScreenToFrameBufferFunction;
175 }
176
177 void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
178 {
179   mMappingConnector.SetActor( mappingActor );
180 }
181
182 Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
183 {
184   return mMappingConnector.mActor;
185 }
186
187 void RenderTask::SetViewportPosition(const Vector2& value)
188 {
189   BakeViewportPositionMessage( GetEventThreadServices(), *mSceneObject, value );
190 }
191
192 Vector2 RenderTask::GetCurrentViewportPosition() const
193 {
194   return mSceneObject->GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
195 }
196
197 void RenderTask::SetViewportSize(const Vector2& value)
198 {
199   BakeViewportSizeMessage( GetEventThreadServices(), *mSceneObject, value );
200 }
201
202 Vector2 RenderTask::GetCurrentViewportSize() const
203 {
204   return mSceneObject->GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
205 }
206
207 void RenderTask::SetViewport( const Viewport& viewport )
208 {
209   SetViewportPosition(Vector2(viewport.x, viewport.y));
210   SetViewportSize(Vector2(viewport.width, viewport.height));
211 }
212
213 void RenderTask::GetViewport( Viewport& viewPort ) const
214 {
215   BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
216
217   if(!mSceneObject->GetViewportEnabled( bufferIndex ))
218   {
219     if ( mFrameBufferImage )
220     {
221       viewPort.x = viewPort.y = 0;
222       viewPort.width = mFrameBufferImage.GetWidth();
223       viewPort.height = mFrameBufferImage.GetHeight();
224     }
225     else
226     {
227       Vector2 size( Stage::GetCurrent()->GetSize() );
228       viewPort.x = viewPort.y = 0;
229       viewPort.width = size.width;
230       viewPort.height = size.height;
231     }
232   }
233   else
234   {
235     const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
236     const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
237     viewPort.x = position.x;
238     viewPort.y = position.y;
239     viewPort.width = size.width;
240     viewPort.height = size.height;
241   }
242 }
243
244 void RenderTask::SetClearColor( const Vector4& color )
245 {
246   if ( mClearColor != color )
247   {
248     mClearColor = color;
249
250     if ( mSceneObject )
251     {
252       // mSceneObject is being used in a separate thread; queue a message to set the value
253       BakeClearColorMessage( GetEventThreadServices(), *mSceneObject, color );
254     }
255   }
256 }
257
258 const Vector4& RenderTask::GetClearColor() const
259 {
260   return mSceneObject->GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
261 }
262
263 void RenderTask::SetClearEnabled( bool enabled )
264 {
265   if ( mClearEnabled != enabled )
266   {
267     mClearEnabled = enabled;
268
269     if ( mSceneObject )
270     {
271       // mSceneObject is being used in a separate thread; queue a message to set the value
272       SetClearEnabledMessage( GetEventThreadServices(), *mSceneObject, mClearEnabled );
273     }
274   }
275 }
276
277 bool RenderTask::GetClearEnabled() const
278 {
279   return mClearEnabled;
280 }
281
282 void RenderTask::SetCullMode( bool mode )
283 {
284   if ( mCullMode != mode )
285   {
286     mCullMode = mode;
287
288     if ( mSceneObject )
289     {
290       // mSceneObject is being used in a separate thread; queue a message to set the value
291       SetCullModeMessage( GetEventThreadServices(), *mSceneObject, mCullMode );
292     }
293   }
294 }
295
296 bool RenderTask::GetCullMode() const
297 {
298   return mCullMode;
299 }
300
301 void RenderTask::SetRefreshRate( unsigned int refreshRate )
302 {
303   DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p  rate:%d\n", this, refreshRate);
304   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
305
306   mRefreshRate = refreshRate; // cached for GetRefreshRate()
307
308   // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
309
310   if ( mSceneObject )
311   {
312     // mSceneObject is being used in a separate thread; queue a message to set the value
313     SetRefreshRateMessage( GetEventThreadServices(), *mSceneObject, refreshRate );
314   }
315 }
316
317 unsigned int RenderTask::GetRefreshRate() const
318 {
319   return mRefreshRate;
320 }
321
322 bool RenderTask::IsHittable( Vector2& screenCoords ) const
323 {
324   // True when input is enabled, source & camera actor are valid
325   bool inputEnabled( false );
326
327   Actor* sourceActor = GetSourceActor();
328   CameraActor* cameraActor = GetCameraActor();
329
330   if ( mInputEnabled  &&
331        NULL != sourceActor    &&
332        sourceActor->OnStage() &&
333        NULL != cameraActor    &&
334        cameraActor->OnStage() )
335   {
336     // If the actors are rendered off-screen, then the screen coordinates must be converted
337     // and the conversion function will tell us if they are inside or outside
338     if ( TranslateCoordinates( screenCoords ) )
339     {
340       // This is a suitable render-task for input handling
341       inputEnabled = true;
342     }
343   }
344
345   return inputEnabled;
346 }
347
348 bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
349 {
350   // return true for on-screen tasks
351   bool inside( true );
352   // If the actors are rendered off-screen, then the screen coordinates must be converted
353   // the function should only be called for offscreen tasks
354   if( mFrameBufferImage && mMappingConnector.mActor )
355   {
356     CameraActor* localCamera = GetCameraActor();
357     StagePtr stage = Stage::GetCurrent();
358     CameraActor& defaultCamera = stage->GetDefaultCameraActor();
359     if( localCamera )
360     {
361       Viewport viewport;
362       Vector2 size( stage->GetSize() );
363       viewport.x = viewport.y = 0;
364       viewport.width = size.width;
365       viewport.height = size.height;
366
367       float localX, localY;
368       inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
369       Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
370       if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
371       {
372         screenCoords.x = localX;
373         screenCoords.y = localY;
374       }
375       else
376       {
377         inside = false;
378       }
379     }
380     else
381     {
382       inside = false;
383     }
384   }
385   else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
386   {
387     inside = mScreenToFrameBufferFunction( screenCoords );
388   }
389   return inside;
390 }
391
392 bool RenderTask::IsSystemLevel() const
393 {
394   return mIsSystemLevel;
395 }
396
397 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
398 {
399   // This should only be called once, with no existing scene-object
400   DALI_ASSERT_DEBUG( NULL == mSceneObject );
401
402   // Keep the raw-pointer until DiscardSceneObject is called
403   mSceneObject = SceneGraph::RenderTask::New();
404
405   // if we have a frame buffer we need to track connection status then send a message to set the frame buffer id in case it has changed since last time we were on stage
406   unsigned int resourceId = 0;
407   if(mFrameBufferImage)
408   {
409     GetImplementation(mFrameBufferImage).Connect();
410
411     resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
412   }
413
414   // mSceneObject is being used in a separate thread; queue a message to set the value
415   SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
416
417   // Send messages to set other properties that may have changed since last time we were on stage
418   SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
419   SetClearColorMessage(  GetEventThreadServices(), *mSceneObject, mClearColor );
420   SetClearEnabledMessage(  GetEventThreadServices(), *mSceneObject, mClearEnabled );
421   SetCullModeMessage(  GetEventThreadServices(), *mSceneObject, mCullMode );
422   SetRefreshRateMessage(  GetEventThreadServices(), *mSceneObject, mRefreshRate );
423
424   // Caller takes ownership
425   return mSceneObject;
426 }
427
428 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
429 {
430   return mSceneObject;
431 }
432
433 void RenderTask::DiscardSceneObject()
434 {
435   // mSceneObject is not owned; throw away the raw-pointer
436   mSceneObject = NULL;
437
438   // if we have a frame buffer we need to track connection status
439   if(mFrameBufferImage)
440   {
441     GetImplementation(mFrameBufferImage).Disconnect();
442   }
443 }
444
445 /********************************************************************************
446  ********************************   PROPERTY METHODS   **************************
447  ********************************************************************************/
448
449 unsigned int RenderTask::GetDefaultPropertyCount() const
450 {
451   return DEFAULT_PROPERTY_COUNT;
452 }
453
454 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
455 {
456   indices.Reserve( DEFAULT_PROPERTY_COUNT );
457
458   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
459   {
460     indices.PushBack( i );
461   }
462 }
463
464 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
465 {
466   if( index < DEFAULT_PROPERTY_COUNT )
467   {
468     return DEFAULT_PROPERTY_DETAILS[index].name;
469   }
470   else
471   {
472     return NULL;
473   }
474 }
475
476 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
477 {
478   Property::Index index = Property::INVALID_INDEX;
479
480   // Look for name in default properties
481   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
482   {
483     if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
484     {
485       index = i;
486       break;
487     }
488   }
489
490   return index;
491 }
492
493 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
494 {
495   return DEFAULT_PROPERTY_DETAILS[ index ].writable;
496 }
497
498 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
499 {
500   return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
501 }
502
503 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
504 {
505   return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
506 }
507
508 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
509 {
510   if( index < DEFAULT_PROPERTY_COUNT )
511   {
512     return DEFAULT_PROPERTY_DETAILS[index].type;
513   }
514
515   // index out of range...return Property::NONE
516   return Property::NONE;
517 }
518
519 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
520 {
521   switch ( index )
522   {
523     case Dali::RenderTask::Property::VIEWPORT_POSITION:
524     {
525       SetViewportPosition( property.Get<Vector2>() );
526       break;
527     }
528     case Dali::RenderTask::Property::VIEWPORT_SIZE:
529     {
530       SetViewportSize( property.Get<Vector2>() );
531       break;
532     }
533     case Dali::RenderTask::Property::CLEAR_COLOR:
534     {
535       SetClearColor( property.Get<Vector4>() );
536       break;
537     }
538     default:
539     {
540       // nothing to do
541       break;
542     }
543   }
544 }
545
546 Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
547 {
548   Property::Value value;
549
550   switch ( index )
551   {
552
553     case Dali::RenderTask::Property::VIEWPORT_POSITION:
554     {
555       value = GetCurrentViewportPosition();
556       break;
557     }
558     case Dali::RenderTask::Property::VIEWPORT_SIZE:
559     {
560       value = GetCurrentViewportSize();
561       break;
562     }
563     case Dali::RenderTask::Property::CLEAR_COLOR:
564     {
565       value = GetClearColor();
566       break;
567     }
568
569     default:
570     {
571       DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
572       break;
573     }
574   }
575
576   return value;
577 }
578
579 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
580 {
581   return mSceneObject;
582 }
583
584 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
585 {
586   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
587
588   const SceneGraph::PropertyBase* property( NULL );
589
590   // This method should only return a property which is part of the scene-graph
591   if( mSceneObject != NULL )
592   {
593     switch ( index )
594     {
595       case Dali::RenderTask::Property::VIEWPORT_POSITION:
596         property = &mSceneObject->mViewportPosition;
597         break;
598
599       case Dali::RenderTask::Property::VIEWPORT_SIZE:
600         property = &mSceneObject->mViewportSize;
601         break;
602
603       case Dali::RenderTask::Property::CLEAR_COLOR:
604         property = &mSceneObject->mClearColor;
605         break;
606
607       default:
608         break;
609     }
610   }
611
612   return property;
613 }
614
615 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
616 {
617   const PropertyInputImpl* property( NULL );
618   if( mSceneObject != NULL )
619   {
620     switch ( index )
621     {
622       case Dali::RenderTask::Property::VIEWPORT_POSITION:
623         property = &mSceneObject->mViewportPosition;
624         break;
625
626       case Dali::RenderTask::Property::VIEWPORT_SIZE:
627         property = &mSceneObject->mViewportSize;
628         break;
629
630       case Dali::RenderTask::Property::CLEAR_COLOR:
631         property = &mSceneObject->mViewportSize;
632         break;
633
634       default:
635         break;
636     }
637   }
638
639   return property;
640 }
641
642 bool RenderTask::HasFinished()
643 {
644   bool finished = false;
645   const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
646
647   if( mRefreshOnceCounter < counter )
648   {
649     finished = true;
650     mRefreshOnceCounter = counter;
651   }
652
653   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p  SC\n", finished?"T":"F", mSceneObject);
654
655   return finished;
656 }
657
658 void RenderTask::EmitSignalFinish()
659 {
660   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
661
662   if( !mSignalFinished.Empty() )
663   {
664     Dali::RenderTask handle( this );
665     mSignalFinished.Emit(handle );
666   }
667 }
668
669 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
670 {
671   return mSignalFinished;
672 }
673
674 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
675 {
676   bool connected( true );
677   RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
678
679   if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
680   {
681     renderTask->FinishedSignal().Connect( tracker, functor );
682   }
683   else
684   {
685     // signalName does not match any signal
686     connected = false;
687   }
688
689   return connected;
690 }
691
692 RenderTask::RenderTask( bool isSystemLevel )
693 : mSceneObject( NULL ),
694   mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
695   mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
696   mMappingConnector( Connector::MAPPING_CONNECTOR, *this  ),
697   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
698   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
699   mRefreshOnceCounter( 0u ),
700   mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
701   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
702   mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
703   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
704   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
705   mIsSystemLevel( isSystemLevel )
706 {
707   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
708 }
709
710 RenderTask::~RenderTask()
711 {
712   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
713 }
714
715 // Helper class for connecting Nodes to the scene-graph RenderTask
716
717 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
718 : mType( type ),
719   mRenderTask( renderTask ),
720   mActor( NULL )
721 {
722 }
723
724 RenderTask::Connector::~Connector()
725 {
726   SetActor( NULL );
727 }
728
729 void RenderTask::Connector::SetActor( Actor* actor )
730 {
731   if ( mActor != actor )
732   {
733     if ( mActor )
734     {
735       mActor->RemoveObserver( *this );
736     }
737
738     mActor = actor;
739
740     if ( mActor )
741     {
742       mActor->AddObserver( *this );
743     }
744
745     UpdateRenderTask();
746   }
747 }
748
749 void RenderTask::Connector::SceneObjectAdded( Object& object )
750 {
751   UpdateRenderTask();
752 }
753
754 void RenderTask::Connector::SceneObjectRemoved( Object& object )
755 {
756   UpdateRenderTask();
757 }
758
759 void RenderTask::Connector::ObjectDestroyed( Object& object )
760 {
761   mActor = NULL;
762
763   UpdateRenderTask();
764 }
765
766 void RenderTask::Connector::UpdateRenderTask()
767 {
768   // Guard to allow handle destruction after Core has been destroyed
769   if( Internal::Stage::IsInstalled() &&
770       mRenderTask.mSceneObject )
771   {
772     const SceneGraph::Node* node( NULL );
773
774     // Check whether a Node exists in the scene-graph
775     if ( NULL != mActor )
776     {
777       const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
778       if ( NULL != object )
779       {
780         // actors only point to nodes as their scene objects
781         node = static_cast< const SceneGraph::Node* >( object );
782       }
783     }
784
785     //the mapping node is not used in the scene graph
786     if ( SOURCE_CONNECTOR == mType )
787     {
788       SetSourceNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
789     }
790     else if( CAMERA_CONNECTOR == mType )
791     {
792       SetCameraNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
793     }
794   }
795 }
796
797 } // namespace Internal
798
799 } // namespace Dali