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