1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 
 25 /**
 26  * Base class for ccui.UICCTextField
 27  * @class
 28  * @extends cc.TextFieldTTF
 29  *
 30  * @property {Boolean}  maxLengthEnabled    - Indicate whether max length limit is enabled
 31  * @property {Number}   maxLength           - The max length of the text field
 32  * @property {Boolean}  passwordEnabled     - Indicate whether the text field is for entering password
 33  */
 34 ccui.UICCTextField = cc.TextFieldTTF.extend(/** @lends ccui.UICCTextField# */{
 35     maxLengthEnabled: false,
 36     maxLength: 0,
 37     passwordEnabled: false,
 38     _passwordStyleText: "",
 39     _attachWithIME: false,
 40     _detachWithIME: false,
 41     _insertText: false,
 42     _deleteBackward: false,
 43     _className:"UICCTextField",
 44     ctor: function () {
 45         cc.TextFieldTTF.prototype.ctor.call(this);
 46         this.maxLengthEnabled = false;
 47         this.maxLength = 0;
 48         this.passwordEnabled = false;
 49         this._passwordStyleText = "*";
 50         this._attachWithIME = false;
 51         this._detachWithIME = false;
 52         this._insertText = false;
 53         this._deleteBackward = false;
 54     },
 55     init:function(){
 56         if(ccui.Widget.prototype.init.call(this)){
 57             this.setTouchEnabled(true);
 58             return true;
 59         }
 60         return false;
 61     },
 62     onEnter: function () {
 63         cc.TextFieldTTF.prototype.onEnter.call(this);
 64         cc.TextFieldTTF.prototype.setDelegate.call(this,this);
 65     },
 66 
 67     //CCTextFieldDelegate
 68 
 69     onTextFieldAttachWithIME: function (sender) {
 70         this.setAttachWithIME(true);
 71         return false;
 72     },
 73 
 74     onTextFieldInsertText: function (sender, text, len) {
 75         if (len == 1 && text == "\n") {
 76             return false;
 77         }
 78         this.setInsertText(true);
 79         if (this.maxLengthEnabled) {
 80             if (cc.TextFieldTTF.prototype.getCharCount.call(this) >= this.maxLength) {
 81                 return true;
 82             }
 83         }
 84 
 85         return false;
 86     },
 87 
 88     onTextFieldDeleteBackward: function (sender, delText, nLen) {
 89         this.setDeleteBackward(true);
 90         return false;
 91     },
 92 
 93     onTextFieldDetachWithIME: function (sender) {
 94         this.setDetachWithIME(true);
 95         return false;
 96     },
 97 
 98     insertText: function (text, len) {
 99         var str_text = text;
100         var locString = cc.TextFieldTTF.prototype.getString.call(this);
101         var str_len = locString.length;
102         var multiple, header;
103         if (text != "\n") {
104             if (this.maxLengthEnabled) {
105                 multiple = 1;
106                 header = text.charCodeAt(0);
107                 if (header < 0 || header > 127) {
108                     multiple = 3;
109                 }
110 
111                 if (str_len + len > this.maxLength * multiple) {
112                     str_text = str_text.substr(0, this.maxLength * multiple);
113                     len = this.maxLength * multiple;
114                 }
115             }
116         }
117         cc.TextFieldTTF.prototype.insertText.call(this,str_text, len);
118 
119         // password
120         if (this.passwordEnabled) {
121             if (cc.TextFieldTTF.prototype.getCharCount.call(this) > 0) {
122                 this.setPasswordText(this._inputText);
123             }
124         }
125     },
126 
127     deleteBackward: function () {
128         cc.TextFieldTTF.prototype.deleteBackward.call(this);
129 
130         if (cc.TextFieldTTF.prototype.getCharCount.call(this) > 0) {
131             // password
132             if (this.passwordEnabled) {
133                 this.setPasswordText(this._inputText);
134             }
135         }
136     },
137 
138     openIME: function () {
139         cc.TextFieldTTF.prototype.attachWithIME.call(this);
140     },
141 
142     closeIME: function () {
143         cc.TextFieldTTF.prototype.detachWithIME.call(this);
144     },
145     onDraw:function (sender) {
146         return false;
147     },
148     setMaxLengthEnabled: function (enable) {
149         this.maxLengthEnabled = enable;
150     },
151 
152     isMaxLengthEnabled: function () {
153         return this.maxLengthEnabled;
154     },
155 
156     setMaxLength: function (length) {
157         this.maxLength = length;
158     },
159 
160     getMaxLength: function () {
161         return this.maxLength;
162     },
163 
164     getCharCount: function () {
165         return cc.TextFieldTTF.prototype.getCharCount.call(this);
166     },
167 
168     setPasswordEnabled: function (enable) {
169         this.passwordEnabled = enable;
170     },
171 
172     isPasswordEnabled: function () {
173         return this.passwordEnabled;
174     },
175 
176     setPasswordStyleText: function (styleText) {
177         if (styleText.length > 1) {
178             return;
179         }
180         var header = styleText.charCodeAt(0);
181         if (header < 33 || header > 126) {
182             return;
183         }
184         this._passwordStyleText = styleText;
185     },
186 
187     setPasswordText: function (text) {
188         var tempStr = "";
189         for (var i = 0; i < text.length; ++i) {
190             tempStr += this._passwordStyleText;
191         }
192         cc.LabelTTF.prototype.setString.call(this, tempStr);
193     },
194 
195     setAttachWithIME: function (attach) {
196         this._attachWithIME = attach;
197     },
198 
199     getAttachWithIME: function () {
200         return this._attachWithIME;
201     },
202 
203     setDetachWithIME: function (detach) {
204         this._detachWithIME = detach;
205     },
206 
207     getDetachWithIME: function () {
208         return this._detachWithIME;
209     },
210 
211     setInsertText: function (insert) {
212         this._insertText = insert;
213     },
214 
215     getInsertText: function () {
216         return this._insertText;
217     },
218 
219     setDeleteBackward: function (deleteBackward) {
220         this._deleteBackward = deleteBackward;
221     },
222 
223     getDeleteBackward: function () {
224         return this._deleteBackward;
225     }
226 });
227 
228 ccui.UICCTextField.create = function (placeholder, fontName, fontSize) {
229     var ret = new ccui.UICCTextField();
230     if (ret && ret.initWithString("", fontName, fontSize)) {
231         if (placeholder) {
232             ret.setPlaceHolder(placeholder);
233         }
234         return ret;
235     }
236     return null;
237 };
238 
239 /**
240  * Base class for ccui.TextField
241  * @class
242  * @extends ccui.Widget
243  *
244  * @property {String}   string              - The content string of the label
245  * @property {Number}   placeHolder         - The place holder of the text field
246  * @property {String}   font                - The text field font with a style string: e.g. "18px Verdana"
247  * @property {String}   fontName            - The text field font name
248  * @property {Number}   fontSize            - The text field font size
249  * @property {Boolean}  maxLengthEnabled    - Indicate whether max length limit is enabled
250  * @property {Number}   maxLength           - The max length of the text field
251  * @property {Boolean}  passwordEnabled     - Indicate whether the text field is for entering password
252  */
253 ccui.TextField = ccui.Widget.extend(/** @lends ccui.TextField# */{
254     _textFieldRender: null,
255     _touchWidth: 0,
256     _touchHeight: 0,
257     _useTouchArea: false,
258     _textFieldEventListener: null,
259     _textFieldEventSelector: null,
260     _attachWithIMEListener: null,
261     _detachWithIMEListener: null,
262     _insertTextListener: null,
263     _deleteBackwardListener: null,
264     _attachWithIMESelector: null,
265     _detachWithIMESelector: null,
266     _insertTextSelector: null,
267     _deleteBackwardSelector: null,
268     _passwordStyleText:"",
269     ctor: function () {
270         ccui.Widget.prototype.ctor.call(this);
271         this._textFieldRender = null;
272         this._touchWidth = 0;
273         this._touchHeight = 0;
274         this._useTouchArea = false;
275 
276         this._textFieldEventListener = null;
277         this._textFieldEventSelector = null;
278         this._attachWithIMEListener = null;
279         this._detachWithIMEListener = null;
280         this._insertTextListener = null;
281         this._deleteBackwardListener = null;
282         this._attachWithIMESelector = null;
283         this._detachWithIMESelector = null;
284         this._insertTextSelector = null;
285         this._deleteBackwardSelector = null;
286     },
287 
288     onEnter:function(){
289         ccui.Widget.prototype.onEnter.call(this);
290         this.setUpdateEnabled(true);
291     },
292 
293     initRenderer: function () {
294         this._textFieldRender = ccui.UICCTextField.create("input words here", "Thonburi", 20);
295         cc.Node.prototype.addChild.call(this, this._textFieldRender, ccui.TextField.RENDERER_ZORDER, -1);
296 
297     },
298 
299     /**
300      * Set touch size
301      * @param {cc.Size} size
302      */
303     setTouchSize: function (size) {
304         this._useTouchArea = true;
305         this._touchWidth = size.width;
306         this._touchHeight = size.height;
307     },
308 
309     /**
310      * Get touch size.
311      * @returns {cc.Size}
312      */
313     getTouchSize:function(){
314         return cc.size(this._touchWidth,this._touchHeight);
315     },
316 
317     /**
318      *  Changes the string value of textField.
319      * @param {String} text
320      */
321     setText: function (text) {
322         if (!text) {
323             return;
324         }
325         text = String(text);
326         if (this.isMaxLengthEnabled()) {
327             text = text.substr(0, this.getMaxLength());
328         }
329         if (this.isPasswordEnabled()) {
330             this._textFieldRender.setPasswordText(text);
331             this._textFieldRender.insertText(text, text.length);
332         }
333         else {
334             this._textFieldRender.setString(text);
335         }
336         this._textFieldRender.setString(text);
337         this.textfieldRendererScaleChangedWithSize();
338     },
339 
340     /**
341      * @param {String} value
342      */
343     setPlaceHolder: function (value) {
344         this._textFieldRender.setPlaceHolder(value);
345         this.textfieldRendererScaleChangedWithSize();
346     },
347 
348     /**
349      * @returns {String}
350      */
351     getPlaceHolder:function(){
352         return this._textFieldRender.getPlaceHolder();
353     },
354 
355 	_setFont: function (font) {
356 		this._textFieldRender._setFont(font);
357 		this.textfieldRendererScaleChangedWithSize();
358 	},
359 
360 	_getFont: function () {
361 		return this._textFieldRender._getFont();
362 	},
363 
364     /**
365      * Set font size for text field content
366      * @param {cc.Size} size
367      */
368     setFontSize: function (size) {
369         this._textFieldRender.setFontSize(size);
370         this.textfieldRendererScaleChangedWithSize();
371     },
372 
373 	/**
374 	 * Get font size for text field content
375 	 * @param {cc.Size} size
376 	 */
377 	getFontSize: function () {
378 		return this._textFieldRender.getFontSize();
379 	},
380 
381     /**
382      * Set font name for text field content
383      * @param {String} name
384      */
385     setFontName: function (name) {
386         this._textFieldRender.setFontName(name);
387         this.textfieldRendererScaleChangedWithSize();
388     },
389 
390 	/**
391 	 * Get font name for text field content
392 	 * @param {cc.Size} size
393 	 */
394 	getFontName: function () {
395 		return this._textFieldRender.getFontName();
396 	},
397 
398     /**
399      * detach with IME
400      */
401     didNotSelectSelf: function () {
402         this._textFieldRender.detachWithIME();
403     },
404 
405     /**
406      * get textField string value
407      * @returns {String}
408      */
409     getStringValue: function () {
410         return this._textFieldRender.getString();
411     },
412 
413     /**
414      * touch began
415      * @param {cc.Point} touchPoint
416      */
417     onTouchBegan: function (touchPoint) {
418         var pass = ccui.Widget.prototype.onTouchBegan.call(this, touchPoint);
419         return pass;
420     },
421 
422     /**
423      * touch ended
424      * @param touchPoint
425      */
426     onTouchEnded: function (touchPoint) {
427         ccui.Widget.prototype.onTouchEnded.call(this, touchPoint);
428         this._textFieldRender.attachWithIME();
429     },
430 
431     /**
432      * @param {Boolean} enable
433      */
434     setMaxLengthEnabled: function (enable) {
435         this._textFieldRender.setMaxLengthEnabled(enable);
436     },
437 
438     /**
439      * @returns {Boolean}
440      */
441     isMaxLengthEnabled: function () {
442         return this._textFieldRender.isMaxLengthEnabled();
443     },
444 
445     /**
446      * @param {number} length
447      */
448     setMaxLength: function (length) {
449         this._textFieldRender.setMaxLength(length);
450     },
451 
452     /**
453      * @returns {number} length
454      */
455     getMaxLength: function () {
456         return this._textFieldRender.getMaxLength();
457     },
458 
459     /**
460      * @param {Boolean} enable
461      */
462     setPasswordEnabled: function (enable) {
463         this._textFieldRender.setPasswordEnabled(enable);
464     },
465 
466     /**
467      * @returns {Boolean}
468      */
469     isPasswordEnabled: function () {
470         return this._textFieldRender.isPasswordEnabled();
471     },
472 
473     /**
474      * @param {String} enable
475      */
476     setPasswordStyleText: function (styleText) {
477         this._textFieldRender.setPasswordStyleText(styleText);
478         this._passwordStyleText = styleText;
479     },
480 
481     /**
482      * @returns {String}
483      */
484     getPasswordStyleText:function(){
485         return this._passwordStyleText;
486     },
487 
488     update: function (dt) {
489         if (this.getAttachWithIME()) {
490             this.attachWithIMEEvent();
491             this.setAttachWithIME(false);
492         }
493         if (this.getDetachWithIME()) {
494             this.detachWithIMEEvent();
495             this.setDetachWithIME(false);
496         }
497         if (this.getInsertText()) {
498             this.insertTextEvent();
499             this.setInsertText(false);
500 
501             this.textfieldRendererScaleChangedWithSize();
502         }
503         if (this.getDeleteBackward()) {
504             this.deleteBackwardEvent();
505             this.setDeleteBackward(false);
506         }
507     },
508 
509     /**
510      * get whether attach with IME.
511      * @returns {Boolean}
512      */
513     getAttachWithIME: function () {
514         return this._textFieldRender.getAttachWithIME();
515     },
516 
517     /**
518      * set attach with IME.
519      * @param {Boolean} attach
520      */
521     setAttachWithIME: function (attach) {
522         this._textFieldRender.setAttachWithIME(attach);
523     },
524 
525     /**
526      * get whether eetach with IME.
527      * @returns {Boolean}
528      */
529     getDetachWithIME: function () {
530         return this._textFieldRender.getDetachWithIME();
531     },
532 
533     /**
534      * set detach with IME.
535      * @param {Boolean} detach
536      */
537     setDetachWithIME: function (detach) {
538         this._textFieldRender.setDetachWithIME(detach);
539     },
540 
541     /**
542      * get insertText
543      * @returns {String}
544      */
545     getInsertText: function () {
546         return this._textFieldRender.getInsertText();
547     },
548 
549     /**
550      * set insertText
551      * @param {String} insertText
552      */
553     setInsertText: function (insertText) {
554         this._textFieldRender.setInsertText(insertText);
555     },
556 
557     /**
558      * @returns {Boolean}
559      */
560     getDeleteBackward: function () {
561         return this._textFieldRender.getDeleteBackward();
562     },
563 
564     /**
565      * @param {Boolean} deleteBackward
566      */
567     setDeleteBackward: function (deleteBackward) {
568         this._textFieldRender.setDeleteBackward(deleteBackward);
569     },
570 
571     attachWithIMEEvent: function () {
572         if (this._textFieldEventListener && this._textFieldEventSelector) {
573             this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_ATTACH_WITH_ME);
574         }
575     },
576 
577     detachWithIMEEvent: function () {
578         if (this._textFieldEventListener && this._textFieldEventSelector) {
579             this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_DETACH_WITH_ME);
580         }
581     },
582 
583     insertTextEvent: function () {
584         if (this._textFieldEventListener && this._textFieldEventSelector) {
585             this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_INSERT_TEXT);
586         }
587     },
588 
589     deleteBackwardEvent: function () {
590         if (this._textFieldEventListener && this._textFieldEventSelector) {
591             this._textFieldEventSelector.call(this._textFieldEventListener, this, ccui.TextField.EVENT_DELETE_BACKWARD);
592         }
593     },
594 
595     /**
596      * add event listener
597      * @param {Function} selector
598      * @param {Object} target
599      */
600     addEventListenerTextField: function (selector, target) {
601         this._textFieldEventSelector = selector;
602         this._textFieldEventListener = target;
603     },
604 
605     /**
606      * check hit
607      * @param {cc.Point} pt
608      * @returns {boolean}
609      */
610     hitTest: function (pt) {
611         var nsp = this.convertToNodeSpace(pt);
612         var locSize = this._textFieldRender.getContentSize();
613         var bb = cc.rect(-locSize.width * this._anchorPoint.x, -locSize.height * this._anchorPoint.y, locSize.width, locSize.height);
614         if (nsp.x >= bb.x && nsp.x <= bb.x + bb.width && nsp.y >= bb.y && nsp.y <= bb.y + bb.height) {
615             return true;
616         }
617         return false;
618     },
619 
620     /**
621      * override "setAnchorPoint" of widget.
622      * @param {cc.Point|Number} point The anchor point of UILabelBMFont or The anchor point.x of UILabelBMFont.
623      * @param {Number} [y] The anchor point.y of UILabelBMFont.
624      */
625     setAnchorPoint: function (point, y) {
626         if(y === undefined){
627 	        ccui.Widget.prototype.setAnchorPoint.call(this, point);
628 	        this._textFieldRender.setAnchorPoint(point);
629         } else {
630 	        ccui.Widget.prototype.setAnchorPoint.call(this, point, y);
631 	        this._textFieldRender.setAnchorPoint(point, y);
632         }
633     },
634 	_setAnchorX: function (value) {
635 		ccui.Widget.prototype._setAnchorX.call(this, value);
636 		this._textFieldRender._setAnchorX(value);
637 	},
638 	_setAnchorY: function (value) {
639 		ccui.Widget.prototype._setAnchorY.call(this, value);
640 		this._textFieldRender._setAnchorY(value);
641 	},
642 
643     onSizeChanged: function () {
644         ccui.Widget.prototype.onSizeChanged.call(this);
645         this.textfieldRendererScaleChangedWithSize();
646     },
647 
648     textfieldRendererScaleChangedWithSize: function () {
649         if (this._ignoreSize) {
650             this._textFieldRender.setScale(1.0);
651             var rendererSize = this.getContentSize();
652             this._size.width = rendererSize.width;
653             this._size.height = rendererSize.height;
654         }
655         else {
656             var textureSize = this.getContentSize();
657             if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
658                 this._textFieldRender.setScale(1.0);
659                 return;
660             }
661             var scaleX = this._size.width / textureSize.width;
662             var scaleY = this._size.height / textureSize.height;
663             this._textFieldRender.setScaleX(scaleX);
664             this._textFieldRender.setScaleY(scaleY);
665         }
666     },
667 
668     /**
669      * override "getContentSize" method of widget.
670      * @returns {cc.Size}
671      */
672     getContentSize: function () {
673         return this._textFieldRender.getContentSize();
674     },
675 	_getWidth: function () {
676 		return this._textFieldRender._getWidth();
677 	},
678 	_getHeight: function () {
679 		return this._textFieldRender._getHeight();
680 	},
681 
682     /**
683      * override "getContentSize" method of widget.
684      * @returns {cc.Node}
685      */
686     getVirtualRenderer: function () {
687         return this._textFieldRender;
688     },
689 
690     updateTextureColor: function () {
691         this.updateColorToRenderer(this._textFieldRender);
692     },
693 
694     updateTextureOpacity: function () {
695         this.updateOpacityToRenderer(this._textFieldRender);
696     },
697 
698     /**
699      * Returns the "class name" of widget.
700      * @returns {string}
701      */
702     getDescription: function () {
703         return "TextField";
704     },
705 
706     attachWithIME: function () {
707         this._textFieldRender.attachWithIME();
708     },
709 
710     createCloneInstance: function () {
711         return ccui.TextField.create();
712     },
713 
714     copySpecialProperties: function (textField) {
715         this.setText(textField._textFieldRender.getString());
716         this.setPlaceHolder(textField.getStringValue());
717         this.setFontSize(textField._textFieldRender.getFontSize());
718         this.setFontName(textField._textFieldRender.getFontName());
719         this.setMaxLengthEnabled(textField.isMaxLengthEnabled());
720         this.setMaxLength(textField.getMaxLength());
721         this.setPasswordEnabled(textField.isPasswordEnabled());
722         this.setPasswordStyleText(textField._passwordStyleText);
723         this.setAttachWithIME(textField.getAttachWithIME());
724         this.setDetachWithIME(textField.getDetachWithIME());
725         this.setInsertText(textField.getInsertText());
726         this.setDeleteBackward(textField.getDeleteBackward());
727     }
728 });
729 
730 window._p = ccui.TextField.prototype;
731 
732 // Extended properties
733 /** @expose */
734 _p.string;
735 cc.defineGetterSetter(_p, "string", _p.getStringValue, _p.setText);
736 /** @expose */
737 _p.placeHolder;
738 cc.defineGetterSetter(_p, "placeHolder", _p.getPlaceHolder, _p.setPlaceHolder);
739 /** @expose */
740 _p.font;
741 cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
742 /** @expose */
743 _p.fontSize;
744 cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
745 /** @expose */
746 _p.fontName;
747 cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
748 /** @expose */
749 _p.maxLengthEnabled;
750 cc.defineGetterSetter(_p, "maxLengthEnabled", _p.isMaxLengthEnabled, _p.setMaxLengthEnabled);
751 /** @expose */
752 _p.maxLength;
753 cc.defineGetterSetter(_p, "maxLength", _p.getMaxLength, _p.setMaxLength);
754 /** @expose */
755 _p.passwordEnabled;
756 cc.defineGetterSetter(_p, "passwordEnabled", _p.isPasswordEnabled, _p.setPasswordEnabled);
757 
758 delete window._p;
759 
760 /**
761  * allocates and initializes a UITextField.
762  * @constructs
763  * @return {ccui.TextField}
764  * @example
765  * // example
766  * var uiTextField = ccui.TextField.create();
767  */
768 ccui.TextField.create = function () {
769     var uiTextField = new ccui.TextField();
770     if (uiTextField && uiTextField.init()) {
771         return uiTextField;
772     }
773     return null;
774 };
775 
776 // Constants
777 //TextField event
778 ccui.TextField.EVENT_ATTACH_WITH_ME = 0;
779 ccui.TextField.EVENT_DETACH_WITH_ME = 1;
780 ccui.TextField.EVENT_INSERT_TEXT = 2;
781 ccui.TextField.EVENT_DELETE_BACKWARD = 3;
782 
783 ccui.TextField.RENDERER_ZORDER = -1;