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