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