Usage of CustomeView for ScrollContainer and code refactoring accordingly. Also added...
[platform/core/uifw/dali-toolkit.git] / plugins / dali-swig / examples / firstscreen / ScrollContainer.cs
1 using Dali;
2 using System;
3 using System.Runtime.InteropServices;
4 using System.Collections.Generic;
5
6
7 namespace FirstScreen
8 {
9     public class ScrollContainer : CustomView
10     {
11         private View _container;                      // View Container will be the first item added to ScrollContainer and parent to all the items added to the ScrollContainer.
12         private Vector3 _itemSize;                    // Size of the item / images added to the ScrollContainer.
13         private List<View> _itemList;                 // List collection of View items/images  added to the ScrollContainer.
14         private int _itemCount;                       // Number of items / images  added to the ScrollContainer.
15         private int _focusedItem;                     // Index of currently focused View item / image  on the ScrollContainer.
16         private float _scrollDisplacement;            // Used for horizontal pan displacement.
17         private float _currentScrollPosition;         // Used for horizontal scroll position.
18         private float _gap;                           // Used for gap / padding between items / images on the ScrollContainer.
19         private float _width;                         // Width of the ScrollContainer.
20         private float _height;                        // Height of the ScrollContainer.
21         private bool _isFocused;                      // Flag to check if ScrollContainer is enabled or not.
22         private float _marginX;                       // Extra horizontal margin is used to add an extra gap between items / images after a focused and scaled item / image.
23         private float _marginY;                       // Extra vertical margin (not used at the moment).
24         private float _offsetYFactor;                 // Vertical Position offset Factor of item height.
25         private float _offsetX;                       // Horizontal Position offset of ScrollContainer.
26         private Stage _stage;                         // Reference to Dali stage.
27         private Vector2 _stageSize;                   // Reference to Dali stage size.
28         private ImageView _shadowBorder;              // Reference to Shadow border ImageView applied to the focused item on ScrollContainer.
29         private ImageView _spotLight;                 // Reference to SpotLight ImageView applied to the focused item on ScrollContainer.
30         private Animation _spotLightAnimation;        // SpotLight Animation applied to the focused item on ScrollContainer.
31         private Animation _focusAnimation;            // Focused position animation on ScrollContainer.
32         private Animation _scrollAnimation;           // Scroll animation on items of ScrollContainer.
33         private Animation _focusTransitionAnimation;  // Focus Transition (scaling /unscaling) animation on items of ScrollContainer.
34         private Path _circularPath;                   // Circular path used for SpotLight Animation applied to the focused item on ScrollContainer.
35
36         public ScrollContainer() : base(ViewWrapperImpl.CustomViewBehaviour.DISABLE_STYLE_CHANGE_SIGNALS |
37                                         ViewWrapperImpl.CustomViewBehaviour.REQUIRES_KEYBOARD_NAVIGATION_SUPPORT)
38         {
39
40         }
41
42         public bool IsFocused
43         {
44             get
45             {
46                 return _isFocused;
47             }
48         }
49
50         public Dali.View Container
51         {
52             get
53             {
54                 return _container;
55             }
56         }
57
58         public int ItemCount
59         {
60             get
61             {
62                 return _itemCount;
63             }
64         }
65
66         public Vector3 ItemSize
67         {
68             get
69             {
70                 return _itemSize;
71             }
72
73             set
74             {
75                 _itemSize = value;
76
77                 Vector3 topLeft = new Vector3(-0.25f * _itemSize.width, -0.25f * _itemSize.height, 0.0f);
78                 Vector3 topRight = new Vector3(0.25f * _itemSize.width, -0.25f * _itemSize.height, 0.0f);
79                 Vector3 bottomRight = new Vector3(0.25f * _itemSize.width, 0.25f * _itemSize.height, 0.0f);
80                 Vector3 bottomLeft = new Vector3(-0.25f * _itemSize.width, 0.25f * _itemSize.height, 0.0f);
81
82                 _circularPath = new Path();
83                 _circularPath.AddPoint(topLeft);
84                 _circularPath.AddPoint(topRight);
85                 _circularPath.AddPoint(bottomRight);
86                 _circularPath.AddPoint(bottomLeft);
87                 _circularPath.AddPoint(topLeft);
88                 _circularPath.GenerateControlPoints(0.5f);
89             }
90         }
91
92         public float Gap
93         {
94             get
95             {
96                 return _gap;
97             }
98
99             set
100             {
101                 _gap = value;
102             }
103         }
104
105         public float MarginX
106         {
107             get
108             {
109                 return _marginX;
110             }
111
112             set
113             {
114                 _marginX = value;
115             }
116         }
117
118         public float OffsetYFator
119         {
120             get
121             {
122                 return _offsetYFactor;
123             }
124
125             set
126             {
127                 _offsetYFactor = value;
128             }
129         }
130
131         public float OffsetX
132         {
133             get
134             {
135                 return _offsetX;
136             }
137
138             set
139             {
140                 _offsetX = value;
141             }
142         }
143
144         public float MarginY
145         {
146             get
147             {
148                 return _marginY;
149             }
150
151             set
152             {
153                 _marginY = value;
154             }
155         }
156
157         public float Width
158         {
159             get
160             {
161                 return _width;
162             }
163
164             set
165             {
166                 _width = value;
167             }
168         }
169
170         public float Height
171         {
172             get
173             {
174                 return _height;
175             }
176
177             set
178             {
179                 _height = value;
180             }
181         }
182
183         public ImageView ShadowBorder
184         {
185             get
186             {
187                 return _shadowBorder;
188             }
189
190             set
191             {
192                 _shadowBorder = value;
193             }
194         }
195
196         public ImageView SpotLight
197         {
198             get
199             {
200                 return _spotLight;
201             }
202
203             set
204             {
205                 _spotLight = value;
206             }
207         }
208
209         public int FocusedItemID
210         {
211             get
212             {
213                 if (_focusedItem < 0)
214                 {
215                     _focusedItem = 0;
216                 }
217
218                 return _focusedItem;
219             }
220         }
221
222         // This override method is called automatically after the Control has been initialized.
223         // Any second phase initialization is done here.
224         public override void OnInitialize()
225         {
226             _itemSize = new Vector3(0.0f, 0.0f, 0.0f);
227             _gap = 0.0f;
228             _width = 0.0f;
229             _height = 0.0f;
230             _currentScrollPosition = 0.0f;
231             _itemCount = 0;
232             _focusedItem = -1;
233             _isFocused = false;
234             _marginX = 50.0f;
235             _marginY = 0.0f;
236             _offsetYFactor = 0.0f;
237             _offsetX = 0.0f;
238
239             _container = new View();
240             this.Add(_container);
241
242             _itemList = new List<View>();
243
244             this.ParentOrigin = NDalic.ParentOriginTopLeft;
245             this.AnchorPoint = NDalic.AnchorPointTopLeft;
246             this.WidthResizePolicy = "FILL_TO_PARENT";
247             this.HeightResizePolicy = "FILL_TO_PARENT";
248             this.SetKeyboardFocusable(true);
249
250             _container.ParentOrigin = NDalic.ParentOriginTopLeft;
251             _container.AnchorPoint = NDalic.AnchorPointTopLeft;
252             _container.WidthResizePolicy = "FILL_TO_PARENT";
253             _container.HeightResizePolicy = "FILL_TO_PARENT";
254
255             _stage = Stage.GetCurrent();
256             _stageSize = _stage.GetSize();
257
258             _spotLightAnimation = new Animation(Constants.SpotLightDuration);
259             _focusTransitionAnimation = new Animation(Constants.FocusTransitionDuration);
260             _focusAnimation = new Animation(Constants.FocusDuration);
261             _focusAnimation.SetEndAction(Animation.EndAction.BakeFinal);
262             _scrollAnimation = new Animation(Constants.ScrollDuration);
263             _scrollAnimation.SetEndAction(Animation.EndAction.BakeFinal);
264
265             EnableGestureDetection(Gesture.Type.Pan);
266         }
267
268         // This will be invoked automatically if an item/image is added to the ScrollContainer
269         public override void OnChildAdd(Actor actor)
270         {
271             View item = View.DownCast(actor);
272
273             if (item is View && item != _container)
274             {
275                 item.AnchorPoint = NDalic.AnchorPointBottomCenter;
276                 item.ParentOrigin = NDalic.ParentOriginBottomCenter;
277
278                 item.Size = _itemSize;
279                 item.SetKeyboardFocusable(true);
280                 item.Position = GetItemPosition(_itemCount, _currentScrollPosition);
281
282                 item.Name = _itemCount.ToString();
283
284                 //item.ClippingMode = "CLIP_CHILDREN";
285
286                 _container.Add(item);
287                 _itemList.Add(item);
288
289                 _itemCount++;
290                 item.SetKeyboardFocusable(true);
291             }
292         }
293
294         // This will be invoked automatically if an item/image is removed from the ScrollContainer
295         public override void OnChildRemove(Actor actor)
296         {
297             View item = View.DownCast(actor);
298
299             if (item is View && item != _container)
300             {
301                 _container.Remove(item);
302
303                 _itemCount--;
304                 _itemList.Remove(item);
305             }
306         }
307
308         // This override function supports two dimensional keyboard navigation.
309         // This function returns the next keyboard focusable actor in ScrollContainer control towards the given direction.
310         public override Actor GetNextKeyboardFocusableActor(Actor currentFocusedActor, View.KeyboardFocus.Direction direction, bool loopEnabled)
311         {
312             if (direction == View.KeyboardFocus.Direction.LEFT)
313             {
314                 return FocusPrevious(loopEnabled);
315             }
316             else if (direction == View.KeyboardFocus.Direction.RIGHT)
317             {
318                 return FocusNext(loopEnabled);
319             }
320             else
321             {
322                 return currentFocusedActor;
323             }
324         }
325
326         // This override function is invoked before chosen focusable actor will be focused.
327         // This allows the application to preform any actions (i.e. Scroll and SpotLight animations) before the focus is actually moved to the chosen actor.
328         public override void OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
329         {
330             Focus(_focusedItem);
331         }
332
333         // This override function is invoked whenever a pan gesture is detected on this control.
334         // Perform Scroll Animation based upon pan gesture velocity / speed.
335         public override void OnPan(PanGesture pan)
336         {
337             switch (pan.state)
338             {
339             case Gesture.State.Started:
340                 _scrollDisplacement = 0.0f;
341                 break;
342
343             case Gesture.State.Continuing:
344                 _scrollDisplacement = pan.displacement.x;
345                 break;
346
347             case Gesture.State.Finished:
348             case Gesture.State.Cancelled:
349                 float absScrollDistance = _scrollDisplacement;
350                 if (absScrollDistance < 0.0f)
351                     absScrollDistance = 0.0f - absScrollDistance;
352
353                 float scrollSpeed = pan.velocity.x * pan.velocity.x + pan.velocity.y * pan.velocity.y;
354                 float maxScrollSpeed = 40.0f;  // TBD
355                 if (scrollSpeed > maxScrollSpeed)
356                     scrollSpeed = maxScrollSpeed;
357
358                 if (absScrollDistance > 1.0f && scrollSpeed > 0.05f) // Threshold TBD
359                 {
360                     if (_scrollDisplacement > 0.0f) // scroll constant distance in constant speed.
361                     {
362                         Scroll((_itemSize.x + _gap) * 2, GetFirstVisibleItemId());
363                     }
364                     else
365                     {
366                         Scroll(-(_itemSize.x + _gap) * 2, GetFirstVisibleItemId());
367                     }
368                 }
369                 break;
370             }
371         }
372
373         // This function returns current focused actor
374         public View GetCurrentFocusedActor()
375         {
376             if (_focusedItem < 0)
377             {
378                 _focusedItem = 0;
379             }
380
381             return _itemList[_focusedItem];
382         }
383
384         public void SetFocused(bool focused)
385         {
386             _isFocused = focused;
387
388             // Perform Focus animation if the ScrollContainer is not focused already
389             if (!_isFocused)
390             {
391                 Actor parent = _shadowBorder.GetParent();
392                 if (parent)
393                 {
394                     parent.Remove(_shadowBorder);
395                 }
396
397                 parent = _spotLight.GetParent();
398                 if (parent)
399                 {
400                     parent.Remove(_spotLight);
401                 }
402
403                 _focusTransitionAnimation.Clear();
404
405                 for (int i = 0; i < _itemList.Count; ++i)
406                 {
407                     SetupItemRenderer(_itemList[i], false);
408
409                     Vector3 targetPosition = GetItemPosition(i, _currentScrollPosition);
410                     _focusTransitionAnimation.AnimateTo(new Dali.Property(_itemList[i], Actor.Property.POSITION),
411                                                         new Dali.Property.Value(targetPosition),
412                                                         new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
413
414                     _focusTransitionAnimation.AnimateTo(new Dali.Property(_itemList[i], Actor.Property.SCALE),
415                                                         new Dali.Property.Value(new Vector3(1.0f, 1.0f, 1.0f)),
416                                                         new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
417                 }
418
419                 _focusTransitionAnimation.Play();
420             }
421             else
422             {
423                 Focus(_focusedItem);
424             }
425         }
426
427         // Obtain ID of first visible item/image on the screen of the ScrollContainer
428         private int GetFirstVisibleItemId()
429         {
430             int firstItemId = -1;
431
432             if (_isFocused)
433             {
434                 firstItemId = (int)Math.Floor((-1.0 * _currentScrollPosition + _marginX * 2.0f) / (_itemSize.x + _gap));
435             }
436             else
437             {
438                 firstItemId = (int)Math.Floor(-1.0 * _currentScrollPosition / (_itemSize.x + _gap));
439             }
440
441             if (firstItemId < 0)
442             {
443                 firstItemId = 0;
444             }
445
446             return firstItemId;
447         }
448
449         // Obtain ID of last visible item/image on the screen of the ScrollContainer
450         private int GetLastVisibleItemId()
451         {
452             int lastItemId = -1;
453
454             if (_isFocused)
455             {
456                 lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition - _marginX * 2.0f) / _itemSize.x) - 1);
457             }
458             else
459             {
460                 lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition) / _itemSize.x) - 1);
461             }
462
463             if (lastItemId >= _itemList.Count)
464             {
465
466                 lastItemId = _itemList.Count - 1;
467             }
468
469             return lastItemId;
470         }
471
472         // Obtain Next item/image (Right of the currently focused item) of the ScrollContainer
473         private Actor FocusNext(bool loopEnabled)
474         {
475             int nextItem = -1;
476
477             if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId())
478             {
479                 nextItem = GetFirstVisibleItemId();
480             }
481             else
482             {
483                 nextItem = _focusedItem + 1;
484             }
485
486             if (nextItem >= _itemList.Count)
487             {
488                 if (loopEnabled)
489                 {
490                     nextItem = 0;
491                 }
492                 else
493                 {
494                     nextItem = _itemList.Count - 1;
495                 }
496             }
497
498             _focusedItem = nextItem;
499             return _itemList[_focusedItem];
500         }
501
502         // Obtain Previous item/image (left of the currently focused item) of the ScrollContainer
503         private Actor FocusPrevious(bool loopEnabled)
504         {
505             int previousItem = -1;
506
507             if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId())
508             {
509                 previousItem = GetFirstVisibleItemId();
510             }
511             else
512             {
513                 previousItem = _focusedItem - 1;
514             }
515
516             if (previousItem < 0)
517             {
518                 if (loopEnabled)
519                 {
520                     previousItem = _itemList.Count - 1;
521                 }
522                 else
523                 {
524                     previousItem = 0;
525                 }
526             }
527
528             _focusedItem = previousItem;
529             return _itemList[_focusedItem];
530         }
531
532         // Perform ScrollAnimation on each item
533         private void Scroll(float amount, int baseItem)
534         {
535             float tagetScrollPosition = _currentScrollPosition + amount;
536             float totalItemSize = _itemList.Count * (_itemSize.width + _gap) + _gap + (_marginX * 2.0f);
537
538             float maxScrollPosition = _width - totalItemSize;
539
540             if (tagetScrollPosition < maxScrollPosition)
541             {
542                 tagetScrollPosition = maxScrollPosition;
543             }
544             if (tagetScrollPosition > 0.0f)
545             {
546                 tagetScrollPosition = 0.0f;
547             }
548             _scrollAnimation.Clear();
549
550             for (int i = 0; i < _itemList.Count; ++i)
551             {
552                 Vector3 targetPosition = GetItemPosition(i, tagetScrollPosition);
553                 _scrollAnimation.AnimateTo(new Dali.Property(_itemList[i], Actor.Property.POSITION),
554                                            new Dali.Property.Value(targetPosition),
555                                            new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
556             }
557
558             _currentScrollPosition = tagetScrollPosition;
559             _scrollAnimation.Play();
560         }
561
562         // This function uses ItemId as next FocusedItem and preforms Scroll and SpotLight animations on that item.
563         private void Focus(int itemId)
564         {
565             if (itemId < 0)
566             {
567                 itemId = 0;
568             }
569             else if (itemId >= _itemList.Count)
570             {
571                 itemId = _itemList.Count - 1;
572             }
573
574             _itemList[itemId].Add(_shadowBorder);
575             _itemList[itemId].Add(_spotLight);
576
577             // Perform Spot Light animation
578             if(_focusedItem != itemId && _spotLight != null)
579             {
580                 _spotLightAnimation.Clear();
581                 _spotLightAnimation.Animate( _spotLight, _circularPath, new Vector3(0.0f, 0.0f, 0.0f) );
582                 _spotLightAnimation.SetLooping(true);
583                 _spotLightAnimation.Play();
584             }
585
586             _focusedItem = itemId;
587
588             Vector3 itemPosition = GetItemPosition(_focusedItem, _currentScrollPosition);
589
590             _focusAnimation.Clear();
591
592             float relativeItemPositionX = itemPosition.x - _itemSize.width * 0.5f + (_stageSize.width * 0.5f) + _offsetX;
593             if (relativeItemPositionX < _marginX + _offsetX + _gap)
594             {
595                 float amount = _marginX + _offsetX + _gap - relativeItemPositionX;
596                 Scroll(amount, itemId + 1); // Perform Scroll animation
597             }
598             else if (relativeItemPositionX + _itemSize.width + _gap + _marginX > _stageSize.width)
599             {
600                 float amount = relativeItemPositionX + _marginX + _gap + _itemSize.width - _stageSize.width;
601                 Scroll(-amount, itemId - 1); // Perform Scroll animation
602             }
603             else
604             {
605                 // Perform animation when item is focused
606                 for (int i = 0; i < _itemList.Count; ++i)
607                 {
608                     Vector3 targetPosition = GetItemPosition(i, _currentScrollPosition);
609                     _focusAnimation.AnimateTo(new Dali.Property(_itemList[i], Actor.Property.POSITION),
610                                               new Dali.Property.Value(targetPosition),
611                                               new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
612                 }
613             }
614
615             for (int i = 0; i < _itemList.Count; ++i)
616             {
617                 SetupItemRenderer(_itemList[i], false);
618
619                 // Perform scale animation on Focused item
620                 if (i == _focusedItem)
621                 {
622                     _focusAnimation.AnimateTo(new Dali.Property(_itemList[i], Actor.Property.SCALE),
623                                               new Dali.Property.Value(new Vector3(1.2f, 1.2f, 1.2f)),
624                                               new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
625                 }
626                 else
627                 {
628                     _focusAnimation.AnimateTo(new Dali.Property(_itemList[i], Actor.Property.SCALE),
629                                               new Dali.Property.Value(new Vector3(1.0f, 1.0f, 1.0f)),
630                                               new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE));
631                 }
632             }
633
634             _focusAnimation.Play();
635
636             if (_isFocused && _focusedItem >= 0)
637             {
638                 SetupItemRenderer(_itemList[_focusedItem], true);
639                 SetupSpotLightRenderer();
640             }
641         }
642
643         // Calculate Position of any item/image of ScrollContainer
644         private Vector3 GetItemPosition(int itemId, float scrollPosition)
645         {
646             if (_isFocused)
647             {
648                 // used (_itemSize.width * 0.5f) because of AnchorPointCenter
649                 // used (_stageSize.width * 0.5f) because of ParentOriginCenter
650                 if (_focusedItem > itemId)
651                 {
652                     float positionX = (_itemSize.width * itemId) + (_gap * (itemId + 1)) + scrollPosition + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f);
653                     return new Vector3(positionX, -_itemSize.height * _offsetYFactor, 0.0f);
654                 }
655                 else if (_focusedItem == itemId)
656                 {
657                     float positionX = (_itemSize.width * itemId) + (_gap * (itemId + 1)) + scrollPosition + _marginX + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f);
658                     return new Vector3(positionX, -_itemSize.height * _offsetYFactor, 0.0f);
659                 }
660                 else
661                 {
662                     float positionX = (_itemSize.width * itemId) + (_gap * (itemId + 1)) + scrollPosition + _marginX * 2.0f + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f);
663                     return new Vector3(positionX, -_itemSize.height * _offsetYFactor, 0.0f);
664                 }
665             }
666             else
667             {
668                 float positionX = (_itemSize.width * itemId) + (_gap * (itemId + 1)) + scrollPosition + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f);
669                 return new Vector3(positionX, -_itemSize.height * _offsetYFactor, 0.0f);
670             }
671         }
672
673         // Used for SpotLight animation with clipping
674         private void SetupItemRenderer(Actor actor, bool stencilOn)
675         {
676             if (actor)
677             {
678                 Renderer renderer = actor.GetRendererAt(0);
679
680                 if (renderer)
681                 {
682                     // Setup the renderer properties:
683                     // The stencil plane is only for stencilling, so disable writing to color buffer.
684
685                     // Enable stencil. Draw to the stencil buffer (only).
686                     if (stencilOn)
687                     {
688                         renderer.RenderMode = (int)RenderModeType.COLOR_STENCIL;
689                     }
690                     else
691                     {
692                         renderer.RenderMode = (int)RenderModeType.COLOR;
693                     }
694                     renderer.StencilFunction = (int)StencilFunctionType.ALWAYS;
695                     renderer.StencilFunctionReference = 1;
696                     renderer.StencilFunctionMask = 0xFF;
697                     renderer.StencilOperationOnFail = (int)StencilOperationType.KEEP;
698                     renderer.StencilOperationOnZFail = (int)StencilOperationType.KEEP;
699                     renderer.StencilOperationOnZPass = (int)StencilOperationType.REPLACE;
700                     renderer.StencilMask = 0xFF;
701
702                     // We don't want to write to the depth buffer.
703                     renderer.DepthWriteMode = (int)DepthWriteModeType.OFF;
704                     // We don't beed to test the depth buffer.
705                     renderer.DepthTestMode = (int)DepthTestModeType.OFF;
706
707                     // This object must be rendered 1st.
708                     renderer.DepthIndex = 10;
709                 }
710             }
711         }
712
713         // Used for SpotLight animation with clipping
714         private void SetupSpotLightRenderer()
715         {
716             if (_spotLight)
717             {
718                 Renderer renderer = _spotLight.GetRendererAt(0);
719
720                 if (renderer)
721                 {
722                     // Setup the renderer properties:
723                     // Write to color buffer so soptlight is visible
724
725                     // We use blending to blend the spotlight with the poster image.
726                     renderer.BlendMode = (int)BlendModeType.ON;
727                     renderer.BlendEquationRgb = (int)BlendEquationType.ADD;
728                     renderer.BlendEquationAlpha = (int)BlendEquationType.ADD;
729                     renderer.BlendFactorDestRgb = (int)BlendFactorType.ONE;
730
731                     // Enable stencil. Here we only draw to areas within the stencil.
732                     renderer.RenderMode = (int)RenderModeType.COLOR_STENCIL;
733                     renderer.StencilFunction = (int)StencilFunctionType.EQUAL;
734                     renderer.StencilFunctionReference = 1;
735                     renderer.StencilFunctionMask = 0xFF;
736                     // Don't write to the stencil.
737                     renderer.StencilMask = 0x00;
738
739                     // We don't need to write to the depth buffer.
740                     renderer.DepthWriteMode = (int)DepthWriteModeType.OFF;
741                     // We don't need to test the depth buffer.
742                     renderer.DepthTestMode = (int)DepthTestModeType.OFF;
743
744                     // This object must be rendered last.
745                     renderer.DepthIndex = 20;
746                 }
747             }
748         }
749     }
750 }
751