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