Merge "Fix prevent issue - GetCurrent() might return null" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / render-tasks / render-task-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/render-tasks/render-task-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/internal/event/common/event-thread-services.h>
28 #include <dali/internal/event/actors/actor-impl.h>
29 #include <dali/internal/event/actors/camera-actor-impl.h>
30 #include <dali/internal/event/common/property-helper.h>
31 #include <dali/internal/event/common/stage-impl.h>
32 #include <dali/internal/event/images/frame-buffer-image-impl.h>
33 #include <dali/internal/update/nodes/node.h>
34 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
35
36 #if defined(DEBUG_ENABLED)
37 namespace
38 {
39 Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
40 }
41 #endif
42
43 namespace Dali
44 {
45
46 namespace Internal
47 {
48
49 namespace // For internal properties
50 {
51
52 // Properties
53
54 //              Name                 Type     writable animatable constraint-input  enum for index-checking
55 DALI_PROPERTY_TABLE_BEGIN
56 DALI_PROPERTY( "viewport-position",  VECTOR2,    true,    true,    true,    Dali::RenderTask::Property::VIEWPORT_POSITION )
57 DALI_PROPERTY( "viewport-size",      VECTOR2,    true,    true,    true,    Dali::RenderTask::Property::VIEWPORT_SIZE     )
58 DALI_PROPERTY( "clear-color",        VECTOR4,    true,    true,    true,    Dali::RenderTask::Property::CLEAR_COLOR       )
59 DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
60
61 // Signals
62
63 const char* const SIGNAL_FINISHED = "finished";
64
65 TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL );
66
67 SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
68
69 } // Unnamed namespace
70
71 RenderTask* RenderTask::New( bool isSystemLevel )
72 {
73   RenderTask* task( new RenderTask( 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( GetEventThreadServices(), *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( GetEventThreadServices(), *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   BakeViewportPositionMessage( GetEventThreadServices(), *mSceneObject, value );
190 }
191
192 Vector2 RenderTask::GetCurrentViewportPosition() const
193 {
194   return mSceneObject->GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
195 }
196
197 void RenderTask::SetViewportSize(const Vector2& value)
198 {
199   BakeViewportSizeMessage( GetEventThreadServices(), *mSceneObject, value );
200 }
201
202 Vector2 RenderTask::GetCurrentViewportSize() const
203 {
204   return mSceneObject->GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
205 }
206
207 void RenderTask::SetViewport( const Viewport& viewport )
208 {
209   SetViewportPosition(Vector2(viewport.x, viewport.y));
210   SetViewportSize(Vector2(viewport.width, viewport.height));
211 }
212
213 void RenderTask::GetViewport( Viewport& viewPort ) const
214 {
215   BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
216
217   if(!mSceneObject->GetViewportEnabled( bufferIndex ))
218   {
219     if ( mFrameBufferImage )
220     {
221       viewPort.x = viewPort.y = 0;
222       viewPort.width = mFrameBufferImage.GetWidth();
223       viewPort.height = mFrameBufferImage.GetHeight();
224     }
225     else
226     {
227       Internal::Stage* stage = Internal::Stage::GetCurrent();
228       if ( stage )
229       {
230         Vector2 size( stage->GetSize() );
231         viewPort.x = viewPort.y = 0;
232         viewPort.width = size.width;
233         viewPort.height = size.height;
234       }
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       BakeClearColorMessage( GetEventThreadServices(), *mSceneObject, color );
258     }
259   }
260 }
261
262 const Vector4& RenderTask::GetClearColor() const
263 {
264   return mSceneObject->GetClearColor( GetEventThreadServices().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( GetEventThreadServices(), *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( GetEventThreadServices(), *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( GetEventThreadServices(), *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     if( stage )
363     {
364       CameraActor& defaultCamera = stage->GetDefaultCameraActor();
365       if( localCamera )
366       {
367         Viewport viewport;
368         Vector2 size( stage->GetSize() );
369         viewport.x = viewport.y = 0;
370         viewport.width = size.width;
371         viewport.height = size.height;
372
373         float localX, localY;
374         inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
375         Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
376         if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
377         {
378           screenCoords.x = localX;
379           screenCoords.y = localY;
380         }
381         else
382         {
383           inside = false;
384         }
385       }
386       else
387       {
388         inside = false;
389       }
390     }
391   }
392   else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
393   {
394     inside = mScreenToFrameBufferFunction( screenCoords );
395   }
396   return inside;
397 }
398
399 bool RenderTask::IsSystemLevel() const
400 {
401   return mIsSystemLevel;
402 }
403
404 SceneGraph::RenderTask* RenderTask::CreateSceneObject()
405 {
406   // This should only be called once, with no existing scene-object
407   DALI_ASSERT_DEBUG( NULL == mSceneObject );
408
409   // Keep the raw-pointer until DiscardSceneObject is called
410   mSceneObject = SceneGraph::RenderTask::New();
411
412   // 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
413   unsigned int resourceId = 0;
414   if(mFrameBufferImage)
415   {
416     GetImplementation(mFrameBufferImage).Connect();
417
418     resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
419   }
420
421   // mSceneObject is being used in a separate thread; queue a message to set the value
422   SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
423
424   // Send messages to set other properties that may have changed since last time we were on stage
425   SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
426   SetClearColorMessage(  GetEventThreadServices(), *mSceneObject, mClearColor );
427   SetClearEnabledMessage(  GetEventThreadServices(), *mSceneObject, mClearEnabled );
428   SetCullModeMessage(  GetEventThreadServices(), *mSceneObject, mCullMode );
429   SetRefreshRateMessage(  GetEventThreadServices(), *mSceneObject, mRefreshRate );
430
431   // Caller takes ownership
432   return mSceneObject;
433 }
434
435 SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
436 {
437   return mSceneObject;
438 }
439
440 void RenderTask::DiscardSceneObject()
441 {
442   // mSceneObject is not owned; throw away the raw-pointer
443   mSceneObject = NULL;
444
445   // if we have a frame buffer we need to track connection status
446   if(mFrameBufferImage)
447   {
448     GetImplementation(mFrameBufferImage).Disconnect();
449   }
450 }
451
452 /********************************************************************************
453  ********************************   PROPERTY METHODS   **************************
454  ********************************************************************************/
455
456 unsigned int RenderTask::GetDefaultPropertyCount() const
457 {
458   return DEFAULT_PROPERTY_COUNT;
459 }
460
461 void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
462 {
463   indices.Reserve( DEFAULT_PROPERTY_COUNT );
464
465   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
466   {
467     indices.PushBack( i );
468   }
469 }
470
471 const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
472 {
473   if( index < DEFAULT_PROPERTY_COUNT )
474   {
475     return DEFAULT_PROPERTY_DETAILS[index].name;
476   }
477   else
478   {
479     return NULL;
480   }
481 }
482
483 Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
484 {
485   Property::Index index = Property::INVALID_INDEX;
486
487   // Look for name in default properties
488   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
489   {
490     if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
491     {
492       index = i;
493       break;
494     }
495   }
496
497   return index;
498 }
499
500 bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
501 {
502   return DEFAULT_PROPERTY_DETAILS[ index ].writable;
503 }
504
505 bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
506 {
507   return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
508 }
509
510 bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
511 {
512   return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
513 }
514
515 Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
516 {
517   if( index < DEFAULT_PROPERTY_COUNT )
518   {
519     return DEFAULT_PROPERTY_DETAILS[index].type;
520   }
521
522   // index out of range...return Property::NONE
523   return Property::NONE;
524 }
525
526 void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
527 {
528   switch ( index )
529   {
530     case Dali::RenderTask::Property::VIEWPORT_POSITION:
531     {
532       SetViewportPosition( property.Get<Vector2>() );
533       break;
534     }
535     case Dali::RenderTask::Property::VIEWPORT_SIZE:
536     {
537       SetViewportSize( property.Get<Vector2>() );
538       break;
539     }
540     case Dali::RenderTask::Property::CLEAR_COLOR:
541     {
542       SetClearColor( property.Get<Vector4>() );
543       break;
544     }
545     default:
546     {
547       // nothing to do
548       break;
549     }
550   }
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::Property::VIEWPORT_POSITION:
561     {
562       value = GetCurrentViewportPosition();
563       break;
564     }
565     case Dali::RenderTask::Property::VIEWPORT_SIZE:
566     {
567       value = GetCurrentViewportSize();
568       break;
569     }
570     case Dali::RenderTask::Property::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 const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
587 {
588   return mSceneObject;
589 }
590
591 const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
592 {
593   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
594
595   const SceneGraph::PropertyBase* property( NULL );
596
597   // This method should only return a property which is part of the scene-graph
598   if( mSceneObject != NULL )
599   {
600     switch ( index )
601     {
602       case Dali::RenderTask::Property::VIEWPORT_POSITION:
603         property = &mSceneObject->mViewportPosition;
604         break;
605
606       case Dali::RenderTask::Property::VIEWPORT_SIZE:
607         property = &mSceneObject->mViewportSize;
608         break;
609
610       case Dali::RenderTask::Property::CLEAR_COLOR:
611         property = &mSceneObject->mClearColor;
612         break;
613
614       default:
615         break;
616     }
617   }
618
619   return property;
620 }
621
622 const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
623 {
624   const PropertyInputImpl* property( NULL );
625   if( mSceneObject != NULL )
626   {
627     switch ( index )
628     {
629       case Dali::RenderTask::Property::VIEWPORT_POSITION:
630         property = &mSceneObject->mViewportPosition;
631         break;
632
633       case Dali::RenderTask::Property::VIEWPORT_SIZE:
634         property = &mSceneObject->mViewportSize;
635         break;
636
637       case Dali::RenderTask::Property::CLEAR_COLOR:
638         property = &mSceneObject->mViewportSize;
639         break;
640
641       default:
642         break;
643     }
644   }
645
646   return property;
647 }
648
649 bool RenderTask::HasFinished()
650 {
651   bool finished = false;
652   const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
653
654   if( mRefreshOnceCounter < counter )
655   {
656     finished = true;
657     mRefreshOnceCounter = counter;
658   }
659
660   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p  SC\n", finished?"T":"F", mSceneObject);
661
662   return finished;
663 }
664
665 void RenderTask::EmitSignalFinish()
666 {
667   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
668
669   if( !mSignalFinished.Empty() )
670   {
671     Dali::RenderTask handle( this );
672     mSignalFinished.Emit(handle );
673   }
674 }
675
676 Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
677 {
678   return mSignalFinished;
679 }
680
681 bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
682 {
683   bool connected( true );
684   RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
685
686   if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
687   {
688     renderTask->FinishedSignal().Connect( tracker, functor );
689   }
690   else
691   {
692     // signalName does not match any signal
693     connected = false;
694   }
695
696   return connected;
697 }
698
699 RenderTask::RenderTask( bool isSystemLevel )
700 : mSceneObject( NULL ),
701   mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
702   mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
703   mMappingConnector( Connector::MAPPING_CONNECTOR, *this  ),
704   mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
705   mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
706   mRefreshOnceCounter( 0u ),
707   mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
708   mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
709   mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
710   mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
711   mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
712   mIsSystemLevel( isSystemLevel )
713 {
714   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
715 }
716
717 RenderTask::~RenderTask()
718 {
719   DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
720 }
721
722 // Helper class for connecting Nodes to the scene-graph RenderTask
723
724 RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
725 : mType( type ),
726   mRenderTask( renderTask ),
727   mActor( NULL )
728 {
729 }
730
731 RenderTask::Connector::~Connector()
732 {
733   SetActor( NULL );
734 }
735
736 void RenderTask::Connector::SetActor( Actor* actor )
737 {
738   if ( mActor != actor )
739   {
740     if ( mActor )
741     {
742       mActor->RemoveObserver( *this );
743     }
744
745     mActor = actor;
746
747     if ( mActor )
748     {
749       mActor->AddObserver( *this );
750     }
751
752     UpdateRenderTask();
753   }
754 }
755
756 void RenderTask::Connector::SceneObjectAdded( Object& object )
757 {
758   UpdateRenderTask();
759 }
760
761 void RenderTask::Connector::SceneObjectRemoved( Object& object )
762 {
763   UpdateRenderTask();
764 }
765
766 void RenderTask::Connector::ObjectDestroyed( Object& object )
767 {
768   mActor = NULL;
769
770   UpdateRenderTask();
771 }
772
773 void RenderTask::Connector::UpdateRenderTask()
774 {
775   // Guard to allow handle destruction after Core has been destroyed
776   if( Internal::Stage::IsInstalled() &&
777       mRenderTask.mSceneObject )
778   {
779     const SceneGraph::Node* node( NULL );
780
781     // Check whether a Node exists in the scene-graph
782     if ( NULL != mActor )
783     {
784       const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
785       if ( NULL != object )
786       {
787         // actors only point to nodes as their scene objects
788         node = static_cast< const SceneGraph::Node* >( object );
789       }
790     }
791
792     //the mapping node is not used in the scene graph
793     if ( SOURCE_CONNECTOR == mType )
794     {
795       SetSourceNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
796     }
797     else if( CAMERA_CONNECTOR == mType )
798     {
799       SetCameraNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
800     }
801   }
802 }
803
804 } // namespace Internal
805
806 } // namespace Dali