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