1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 cc._globalFontSize = cc.ITEM_SIZE; 28 cc._globalFontName = "Arial"; 29 cc._globalFontNameRelease = false; 30 31 /** 32 * Subclass cc.MenuItem (or any subclass) to create your custom cc.MenuItem objects. 33 * @class 34 * @extends cc.NodeRGBA 35 * 36 * @property {Boolean} enabled - Indicate whether item is enabled 37 */ 38 cc.MenuItem = cc.NodeRGBA.extend(/** @lends cc.MenuItem# */{ 39 _enabled: false, 40 _target: null, 41 _callback: null, 42 _isSelected: false, 43 _className: "MenuItem", 44 45 /** 46 * Constructor 47 * @constructor 48 * @param {function|String} callback 49 * @param {cc.Node} target 50 */ 51 ctor: function (callback, target) { 52 var nodeP = cc.NodeRGBA.prototype; 53 nodeP.ctor.call(this); 54 this._target = null; 55 this._callback = null; 56 this._isSelected = false; 57 this._enabled = false; 58 59 nodeP.setAnchorPoint.call(this, 0.5, 0.5); 60 this._target = target || null; 61 this._callback = callback || null; 62 if (this._callback) { 63 this._enabled = true; 64 } 65 }, 66 67 /** 68 * MenuItem is selected 69 * @return {Boolean} 70 */ 71 isSelected: function () { 72 return this._isSelected; 73 }, 74 75 setOpacityModifyRGB: function (value) { 76 }, 77 78 isOpacityModifyRGB: function () { 79 return false; 80 }, 81 82 /** 83 * set the target/selector of the menu item 84 * @param {function|String} selector 85 * @param {cc.Node} rec 86 * @deprecated 87 */ 88 setTarget: function (selector, rec) { 89 this._target = rec; 90 this._callback = selector; 91 }, 92 93 /** 94 * MenuItem is Enabled 95 * @return {Boolean} 96 */ 97 isEnabled: function () { 98 return this._enabled; 99 }, 100 101 /** 102 * set enable value of MenuItem 103 * @param {Boolean} enable 104 */ 105 setEnabled: function (enable) { 106 this._enabled = enable; 107 }, 108 109 /** 110 * @param {function|String} callback 111 * @param {cc.Node} target 112 * @return {Boolean} 113 */ 114 initWithCallback: function (callback, target) { 115 this.anchorX = 0.5; 116 this.anchorY = 0.5; 117 this._target = target; 118 this._callback = callback; 119 this._enabled = true; 120 this._isSelected = false; 121 return true; 122 }, 123 124 /** 125 * return rect value of cc.MenuItem 126 * @return {cc.Rect} 127 */ 128 rect: function () { 129 var locPosition = this._position, locContentSize = this._contentSize, locAnchorPoint = this._anchorPoint; 130 return cc.rect(locPosition.x - locContentSize.width * locAnchorPoint.x, 131 locPosition.y - locContentSize.height * locAnchorPoint.y, 132 locContentSize.width, locContentSize.height); 133 }, 134 135 /** 136 * same as setIsSelected(true) 137 */ 138 selected: function () { 139 this._isSelected = true; 140 }, 141 142 /** 143 * same as setIsSelected(false) 144 */ 145 unselected: function () { 146 this._isSelected = false; 147 }, 148 149 /** 150 * set the callback to the menu item 151 * @param {function|String} callback 152 * @param {cc.Node} target 153 */ 154 setCallback: function (callback, target) { 155 this._target = target; 156 this._callback = callback; 157 }, 158 159 /** 160 * call the selector with target 161 */ 162 activate: function () { 163 if (this._enabled) { 164 var locTarget = this._target, locCallback = this._callback; 165 if (!locCallback) 166 return; 167 if (locTarget && (typeof(locCallback) == "string")) { 168 locTarget[locCallback](this); 169 } else if (locTarget && (typeof(locCallback) == "function")) { 170 locCallback.call(locTarget, this); 171 } else 172 locCallback(this); 173 } 174 } 175 }); 176 177 var _p = cc.MenuItem.prototype; 178 179 // Extended properties 180 /** @expose */ 181 _p.enabled; 182 cc.defineGetterSetter(_p, "enabled", _p.isEnabled, _p.setEnabled); 183 184 /** 185 * creates an empty menu item with target and callback<br/> 186 * Not recommended to use the base class, should use more defined menu item classes 187 * @param {function|String} callback callback 188 * @param {cc.Node} target 189 * @return {cc.MenuItem} 190 */ 191 cc.MenuItem.create = function (callback, target) { 192 return new cc.MenuItem(callback, target); 193 }; 194 195 /** 196 * Any cc.Node that supports the cc.LabelProtocol protocol can be added.<br/> 197 * Supported nodes:<br/> 198 * - cc.BitmapFontAtlas<br/> 199 * - cc.LabelAtlas<br/> 200 * - cc.LabelTTF<br/> 201 * @class 202 * @extends cc.MenuItem 203 * 204 * @property {String} string - Content string of label item 205 * @property {cc.Node} label - Label of label item 206 * @property {cc.Color} disabledColor - Color of label when it's diabled 207 */ 208 cc.MenuItemLabel = cc.MenuItem.extend(/** @lends cc.MenuItemLabel# */{ 209 _disabledColor: null, 210 _label: null, 211 _orginalScale: 0, 212 _colorBackup: null, 213 214 /** 215 * @constructor 216 * @param {cc.Node} label 217 * @param {function|String} selector 218 * @param {cc.Node} target 219 */ 220 ctor: function (label, selector, target) { 221 cc.MenuItem.prototype.ctor.call(this, selector, target); 222 this._disabledColor = null; 223 this._label = null; 224 this._orginalScale = 0; 225 this._colorBackup = null; 226 227 if (label) { 228 this._originalScale = 1.0; 229 this._colorBackup = cc.color.WHITE; 230 this._disabledColor = cc.color(126, 126, 126); 231 this.setLabel(label); 232 233 this.cascadeColor = true; 234 this.cascadeOpacity = true; 235 } 236 }, 237 238 /** 239 * @return {cc.Color} 240 */ 241 getDisabledColor: function () { 242 return this._disabledColor; 243 }, 244 245 /** 246 * @param {cc.Color} color 247 */ 248 setDisabledColor: function (color) { 249 this._disabledColor = color; 250 }, 251 252 /** 253 * return label of MenuItemLabel 254 * @return {cc.Node} 255 */ 256 getLabel: function () { 257 return this._label; 258 }, 259 260 /** 261 * @param {cc.Node} label 262 */ 263 setLabel: function (label) { 264 if (label) { 265 this.addChild(label); 266 label.anchorX = 0; 267 label.anchorY = 0; 268 this.width = label.width; 269 this.height = label.height; 270 } 271 272 if (this._label) { 273 this.removeChild(this._label, true); 274 } 275 276 this._label = label; 277 }, 278 279 /** 280 * @param {Boolean} enabled 281 */ 282 setEnabled: function (enabled) { 283 if (this._enabled != enabled) { 284 var locLabel = this._label; 285 if (!enabled) { 286 this._colorBackup = locLabel.color; 287 locLabel.color = this._disabledColor; 288 } else { 289 locLabel.color = this._colorBackup; 290 } 291 } 292 cc.MenuItem.prototype.setEnabled.call(this, enabled); 293 }, 294 295 /** 296 * @param {Number} opacity from 0-255 297 */ 298 setOpacity: function (opacity) { 299 this._label.opacity = opacity; 300 }, 301 302 /** 303 * @return {Number} 304 */ 305 getOpacity: function () { 306 return this._label.opacity; 307 }, 308 309 /** 310 * @param {cc.Color} color 311 */ 312 setColor: function (color) { 313 this._label.color = color; 314 }, 315 316 /** 317 * @return {cc.Color} 318 */ 319 getColor: function () { 320 return this._label.color; 321 }, 322 323 /** 324 * @param {cc.Node} label 325 * @param {function|String} selector 326 * @param {cc.Node} target 327 * @return {Boolean} 328 */ 329 initWithLabel: function (label, selector, target) { 330 this.initWithCallback(selector, target); 331 this._originalScale = 1.0; 332 this._colorBackup = cc.color.WHITE; 333 this._disabledColor = cc.color(126, 126, 126); 334 this.setLabel(label); 335 336 this.cascadeColor = true; 337 this.cascadeOpacity = true; 338 339 return true; 340 }, 341 342 /** 343 * @param {String} label 344 */ 345 setString: function (label) { 346 this._label.string = label; 347 this.width = this._label.width; 348 this.height = this._label.height; 349 }, 350 351 getString: function () { 352 return this._label.string; 353 }, 354 355 /** 356 * activate the menu item 357 */ 358 activate: function () { 359 if (this._enabled) { 360 this.stopAllActions(); 361 this.scale = this._originalScale; 362 cc.MenuItem.prototype.activate.call(this); 363 } 364 }, 365 366 /** 367 * menu item is selected (runs callback) 368 */ 369 selected: function () { 370 if (this._enabled) { 371 cc.MenuItem.prototype.selected.call(this); 372 373 var action = this.getActionByTag(cc.ZOOM_ACTION_TAG); 374 if (action) 375 this.stopAction(action); 376 else 377 this._originalScale = this.scale; 378 379 var zoomAction = cc.ScaleTo.create(0.1, this._originalScale * 1.2); 380 zoomAction.setTag(cc.ZOOM_ACTION_TAG); 381 this.runAction(zoomAction); 382 } 383 }, 384 385 /** 386 * menu item goes back to unselected state 387 */ 388 unselected: function () { 389 if (this._enabled) { 390 cc.MenuItem.prototype.unselected.call(this); 391 this.stopActionByTag(cc.ZOOM_ACTION_TAG); 392 var zoomAction = cc.ScaleTo.create(0.1, this._originalScale); 393 zoomAction.setTag(cc.ZOOM_ACTION_TAG); 394 this.runAction(zoomAction); 395 } 396 } 397 }); 398 399 var _p = cc.MenuItemLabel.prototype; 400 401 // Extended properties 402 /** @expose */ 403 _p.string; 404 cc.defineGetterSetter(_p, "string", _p.getString, _p.setString); 405 /** @expose */ 406 _p.disabledColor; 407 cc.defineGetterSetter(_p, "disabledColor", _p.getDisabledColor, _p.setDisabledColor); 408 /** @expose */ 409 _p.label; 410 cc.defineGetterSetter(_p, "label", _p.getLabel, _p.setLabel); 411 412 413 /** 414 * @param {cc.Node} label 415 * @param {function|String|Null} [selector=] 416 * @param {cc.Node|Null} [target=] 417 * @return {cc.MenuItemLabel} 418 */ 419 cc.MenuItemLabel.create = function (label, selector, target) { 420 return new cc.MenuItemLabel(label, selector, target); 421 }; 422 423 /** 424 * Helper class that creates a MenuItemLabel class with a LabelAtlas 425 * @class 426 * @extends cc.MenuItemLabel 427 */ 428 cc.MenuItemAtlasFont = cc.MenuItemLabel.extend(/** @lends cc.MenuItemAtlasFont# */{ 429 430 /** 431 * @param {String} value 432 * @param {String} charMapFile 433 * @param {Number} itemWidth 434 * @param {Number} itemHeight 435 * @param {String} startCharMap a single character 436 * @param {function|String|Null} callback 437 * @param {cc.Node|Null} target 438 */ 439 ctor: function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) { 440 var label; 441 if (value && value.length > 0) { 442 label = cc.LabelAtlas.create(value, charMapFile, itemWidth, itemHeight, startCharMap); 443 } 444 445 cc.MenuItemLabel.prototype.ctor.call(this, label, callback, target); 446 }, 447 448 /** 449 * @param {String} value 450 * @param {String} charMapFile 451 * @param {Number} itemWidth 452 * @param {Number} itemHeight 453 * @param {String} startCharMap a single character 454 * @param {function|String|Null} callback 455 * @param {cc.Node|Null} target 456 * @return {Boolean} 457 */ 458 initWithString: function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) { 459 if (!value || value.length == 0) 460 throw "cc.MenuItemAtlasFont.initWithString(): value should be non-null and its length should be greater than 0"; 461 462 var label = new cc.LabelAtlas(); 463 label.initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap); 464 if (this.initWithLabel(label, callback, target)) { 465 // do something ? 466 } 467 return true; 468 } 469 }); 470 471 /** 472 * create menu item from string with font 473 * @param {String} value the text to display 474 * @param {String} charMapFile the character map file 475 * @param {Number} itemWidth 476 * @param {Number} itemHeight 477 * @param {String} startCharMap a single character 478 * @param {function|String|Null} [callback=null] 479 * @param {cc.Node|Null} [target=] 480 * @return {cc.MenuItemAtlasFont} 481 * @example 482 * // Example 483 * var item = cc.MenuItemAtlasFont.create('text to display', 'font.fnt', 12, 32, ' ') 484 * 485 * //OR 486 * var item = cc.MenuItemAtlasFont.create('text to display', 'font.fnt', 12, 32, ' ', game.run, game) 487 */ 488 cc.MenuItemAtlasFont.create = function (value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target) { 489 return new cc.MenuItemAtlasFont(value, charMapFile, itemWidth, itemHeight, startCharMap, callback, target); 490 }; 491 492 /** 493 * Helper class that creates a CCMenuItemLabel class with a Label 494 * @class 495 * @extends cc.MenuItemLabel 496 * 497 * @property {Number} fontSize - Font size of font item 498 * @property {String} fontName - Font name of font item 499 */ 500 cc.MenuItemFont = cc.MenuItemLabel.extend(/** @lends cc.MenuItemFont# */{ 501 _fontSize: null, 502 _fontName: null, 503 504 /** 505 * @constructor 506 * @param {String} value text for the menu item 507 * @param {function|String} callback 508 * @param {cc.Node} target 509 */ 510 ctor: function (value, callback, target) { 511 var label; 512 if (value && value.length > 0) { 513 this._fontName = cc._globalFontName; 514 this._fontSize = cc._globalFontSize; 515 label = cc.LabelTTF.create(value, this._fontName, this._fontSize); 516 } 517 else { 518 this._fontSize = 0; 519 this._fontName = ""; 520 } 521 522 cc.MenuItemLabel.prototype.ctor.call(this, label, callback, target); 523 }, 524 525 /** 526 * @param {String} value text for the menu item 527 * @param {function|String} callback 528 * @param {cc.Node} target 529 * @return {Boolean} 530 */ 531 initWithString: function (value, callback, target) { 532 if (!value || value.length == 0) 533 throw "Value should be non-null and its length should be greater than 0"; 534 535 this._fontName = cc._globalFontName; 536 this._fontSize = cc._globalFontSize; 537 538 var label = cc.LabelTTF.create(value, this._fontName, this._fontSize); 539 if (this.initWithLabel(label, callback, target)) { 540 // do something ? 541 } 542 return true; 543 }, 544 545 /** 546 * @param {Number} s 547 */ 548 setFontSize: function (s) { 549 this._fontSize = s; 550 this._recreateLabel(); 551 }, 552 553 /** 554 * 555 * @return {Number} 556 */ 557 getFontSize: function () { 558 return this._fontSize; 559 }, 560 561 /** 562 * @param {String} name 563 */ 564 setFontName: function (name) { 565 this._fontName = name; 566 this._recreateLabel(); 567 }, 568 569 /** 570 * @return {String} 571 */ 572 getFontName: function () { 573 return this._fontName; 574 }, 575 576 _recreateLabel: function () { 577 var label = cc.LabelTTF.create(this._label.string, this._fontName, this._fontSize); 578 this.setLabel(label); 579 } 580 }); 581 582 /** 583 * a shared function to set the fontSize for menuitem font 584 * @param {Number} fontSize 585 */ 586 cc.MenuItemFont.setFontSize = function (fontSize) { 587 cc._globalFontSize = fontSize; 588 }; 589 590 /** 591 * a shared function to get the font size for menuitem font 592 * @return {Number} 593 */ 594 cc.MenuItemFont.fontSize = function () { 595 return cc._globalFontSize; 596 }; 597 598 /** 599 * a shared function to set the fontsize for menuitem font 600 * @param name 601 */ 602 cc.MenuItemFont.setFontName = function (name) { 603 if (cc._globalFontNameRelease) { 604 cc._globalFontName = ''; 605 } 606 cc._globalFontName = name; 607 cc._globalFontNameRelease = true; 608 }; 609 610 var _p = cc.MenuItemFont.prototype; 611 612 // Extended properties 613 /** @expose */ 614 _p.fontSize; 615 cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize); 616 /** @expose */ 617 _p.fontName; 618 cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName); 619 620 621 /** 622 * a shared function to get the font name for menuitem font 623 * @return {String} 624 */ 625 cc.MenuItemFont.fontName = function () { 626 return cc._globalFontName; 627 }; 628 629 /** 630 * create a menu item from string 631 * @param {String} value the text to display 632 * @param {String|function|Null} callback the callback to run, either in function name or pass in the actual function 633 * @param {cc.Node|Null} target the target to run callback 634 * @return {cc.MenuItemFont} 635 * @example 636 * // Example 637 * var item = cc.MenuItemFont.create("Game start", 'start', Game) 638 * //creates a menu item from string "Game start", and when clicked, it will run Game.start() 639 * 640 * var item = cc.MenuItemFont.create("Game start", game.start, Game)//same as above 641 * 642 * var item = cc.MenuItemFont.create("i do nothing")//create a text menu item that does nothing 643 * 644 * //you can set font size and name before or after 645 * cc.MenuItemFont.setFontName('my Fancy Font'); 646 * cc.MenuItemFont.setFontSize(62); 647 */ 648 cc.MenuItemFont.create = function (value, callback, target) { 649 return new cc.MenuItemFont(value, callback, target); 650 }; 651 652 653 /** 654 * CCMenuItemSprite accepts CCNode<CCRGBAProtocol> objects as items.<br/> 655 * The images has 3 different states:<br/> 656 * - unselected image<br/> 657 * - selected image<br/> 658 * - disabled image<br/> 659 * @class 660 * @extends cc.MenuItem 661 * 662 * @property {cc.Sprite} normalImage - Sprite in normal state 663 * @property {cc.Sprite} selectedImage - Sprite in selected state 664 * @property {cc.Sprite} disabledImage - Sprite in disabled state 665 */ 666 cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{ 667 _normalImage: null, 668 _selectedImage: null, 669 _disabledImage: null, 670 671 /** 672 * @constructor 673 * @param {Image|Null} normalSprite normal state image 674 * @param {Image|Null} selectedSprite selected state image 675 * @param {Image|cc.Node|Null} three disabled state image OR target node 676 * @param {String|function|cc.Node|Null} four callback function name in string or actual function, OR target Node 677 * @param {String|function|Null} five callback function name in string or actual function 678 * 679 * @example 680 * // Example 681 * var item = new cc.MenuItemSprite(normalImage)//create a menu item from a sprite with no functionality 682 * var item = new cc.MenuItemSprite(normalImage, selectedImage)//create a menu Item, nothing will happen when clicked 683 * var item = new cc.MenuItemSprite(normalImage, SelectedImage, disabledImage)//same above, but with disabled state image 684 * var item = new cc.MenuItemSprite(normalImage, SelectedImage, 'callback', targetNode)//create a menu item, when clicked runs targetNode.callback() 685 * var item = new cc.MenuItemSprite(normalImage, SelectedImage, disabledImage, targetNode.callback, targetNode) 686 * //same as above, but with disabled image, and passing in callback function 687 */ 688 ctor: function (normalSprite, selectedSprite, three, four, five) { 689 cc.MenuItem.prototype.ctor.call(this); 690 this._normalImage = null; 691 this._selectedImage = null; 692 this._disabledImage = null; 693 694 if (selectedSprite !== undefined) { 695 normalSprite = normalSprite; 696 selectedSprite = selectedSprite; 697 var disabledImage, target, callback; 698 //when you send 4 arguments, five is undefined 699 if (five !== undefined) { 700 disabledImage = three; 701 callback = four; 702 target = five; 703 } else if (four !== undefined && typeof four === "function") { 704 disabledImage = three; 705 callback = four; 706 } else if (four !== undefined && typeof three === "function") { 707 target = four; 708 callback = three; 709 disabledImage = selectedSprite; 710 } else if (three === undefined) { 711 disabledImage = selectedSprite; 712 } 713 this.initWithNormalSprite(normalSprite, selectedSprite, disabledImage, callback, target); 714 } 715 }, 716 717 /** 718 * @return {cc.Sprite} 719 */ 720 getNormalImage: function () { 721 return this._normalImage; 722 }, 723 724 /** 725 * @param {cc.Sprite} normalImage 726 */ 727 setNormalImage: function (normalImage) { 728 if (this._normalImage == normalImage) { 729 return; 730 } 731 if (normalImage) { 732 this.addChild(normalImage, 0, cc.NORMAL_TAG); 733 normalImage.anchorX = 0; 734 normalImage.anchorY = 0; 735 } 736 if (this._normalImage) { 737 this.removeChild(this._normalImage, true); 738 } 739 740 this._normalImage = normalImage; 741 this.width = this._normalImage.width; 742 this.height = this._normalImage.height; 743 this._updateImagesVisibility(); 744 745 if (normalImage.textureLoaded && !normalImage.textureLoaded()) { 746 normalImage.addLoadedEventListener(function (sender) { 747 this.width = sender.width; 748 this.height = sender.height; 749 }, this); 750 } 751 }, 752 753 /** 754 * @return {cc.Sprite} 755 */ 756 getSelectedImage: function () { 757 return this._selectedImage; 758 }, 759 760 /** 761 * @param {cc.Sprite} selectedImage 762 */ 763 setSelectedImage: function (selectedImage) { 764 if (this._selectedImage == selectedImage) 765 return; 766 767 if (selectedImage) { 768 this.addChild(selectedImage, 0, cc.SELECTED_TAG); 769 selectedImage.anchorX = 0; 770 selectedImage.anchorY = 0; 771 } 772 773 if (this._selectedImage) { 774 this.removeChild(this._selectedImage, true); 775 } 776 777 this._selectedImage = selectedImage; 778 this._updateImagesVisibility(); 779 }, 780 781 /** 782 * @return {cc.Sprite} 783 */ 784 getDisabledImage: function () { 785 return this._disabledImage; 786 }, 787 788 /** 789 * @param {cc.Sprite} disabledImage 790 */ 791 setDisabledImage: function (disabledImage) { 792 if (this._disabledImage == disabledImage) 793 return; 794 795 if (disabledImage) { 796 this.addChild(disabledImage, 0, cc.DISABLE_TAG); 797 disabledImage.anchorX = 0; 798 disabledImage.anchorY = 0; 799 } 800 801 if (this._disabledImage) 802 this.removeChild(this._disabledImage, true); 803 804 this._disabledImage = disabledImage; 805 this._updateImagesVisibility(); 806 }, 807 808 /** 809 * @param {cc.Node} normalSprite 810 * @param {cc.Node} selectedSprite 811 * @param {cc.Node} disabledSprite 812 * @param {function|String} callback 813 * @param {cc.Node} target 814 * @return {Boolean} 815 */ 816 initWithNormalSprite: function (normalSprite, selectedSprite, disabledSprite, callback, target) { 817 this.initWithCallback(callback, target); 818 this.setNormalImage(normalSprite); 819 this.setSelectedImage(selectedSprite); 820 this.setDisabledImage(disabledSprite); 821 var locNormalImage = this._normalImage; 822 if (locNormalImage) { 823 this.width = locNormalImage.width; 824 this.height = locNormalImage.height; 825 826 if (locNormalImage.textureLoaded && !locNormalImage.textureLoaded()) { 827 locNormalImage.addLoadedEventListener(function (sender) { 828 this.width = sender.width; 829 this.height = sender.height; 830 this.cascadeColor = true; 831 this.cascadeOpacity = true; 832 }, this); 833 } 834 } 835 this.cascadeColor = true; 836 this.cascadeOpacity = true; 837 return true; 838 }, 839 840 /** 841 * @param {cc.Color} color 842 */ 843 setColor: function (color) { 844 this._normalImage.color = color; 845 846 if (this._selectedImage) 847 this._selectedImage.color = color; 848 849 if (this._disabledImage) 850 this._disabledImage.color = color; 851 }, 852 853 /** 854 * @return {cc.Color} 855 */ 856 getColor: function () { 857 return this._normalImage.color; 858 }, 859 860 /** 861 * @param {Number} opacity 0 - 255 862 */ 863 setOpacity: function (opacity) { 864 this._normalImage.opacity = opacity; 865 866 if (this._selectedImage) 867 this._selectedImage.opacity = opacity; 868 869 if (this._disabledImage) 870 this._disabledImage.opacity = opacity; 871 }, 872 873 /** 874 * @return {Number} opacity from 0 - 255 875 */ 876 getOpacity: function () { 877 return this._normalImage.opacity; 878 }, 879 880 /** 881 * menu item is selected (runs callback) 882 */ 883 selected: function () { 884 cc.MenuItem.prototype.selected.call(this); 885 if (this._normalImage) { 886 if (this._disabledImage) 887 this._disabledImage.visible = false; 888 889 if (this._selectedImage) { 890 this._normalImage.visible = false; 891 this._selectedImage.visible = true; 892 } else 893 this._normalImage.visible = true; 894 } 895 }, 896 897 /** 898 * menu item goes back to unselected state 899 */ 900 unselected: function () { 901 cc.MenuItem.prototype.unselected.call(this); 902 if (this._normalImage) { 903 this._normalImage.visible = true; 904 905 if (this._selectedImage) 906 this._selectedImage.visible = false; 907 908 if (this._disabledImage) 909 this._disabledImage.visible = false; 910 } 911 }, 912 913 /** 914 * @param {Boolean} bEnabled 915 */ 916 setEnabled: function (bEnabled) { 917 if (this._enabled != bEnabled) { 918 cc.MenuItem.prototype.setEnabled.call(this, bEnabled); 919 this._updateImagesVisibility(); 920 } 921 }, 922 923 _updateImagesVisibility: function () { 924 var locNormalImage = this._normalImage, locSelImage = this._selectedImage, locDisImage = this._disabledImage; 925 if (this._enabled) { 926 if (locNormalImage) 927 locNormalImage.visible = true; 928 if (locSelImage) 929 locSelImage.visible = false; 930 if (locDisImage) 931 locDisImage.visible = false; 932 } else { 933 if (locDisImage) { 934 if (locNormalImage) 935 locNormalImage.visible = false; 936 if (locSelImage) 937 locSelImage.visible = false; 938 if (locDisImage) 939 locDisImage.visible = true; 940 } else { 941 if (locNormalImage) 942 locNormalImage.visible = true; 943 if (locSelImage) 944 locSelImage.visible = false; 945 } 946 } 947 } 948 }); 949 950 var _p = cc.MenuItemSprite.prototype; 951 952 // Extended properties 953 /** @expose */ 954 _p.normalImage; 955 cc.defineGetterSetter(_p, "normalImage", _p.getNormalImage, _p.setNormalImage); 956 /** @expose */ 957 _p.selectedImage; 958 cc.defineGetterSetter(_p, "selectedImage", _p.getSelectedImage, _p.setSelectedImage); 959 /** @expose */ 960 _p.disabledImage; 961 cc.defineGetterSetter(_p, "disabledImage", _p.getDisabledImage, _p.setDisabledImage); 962 963 /** 964 * create a menu item from sprite 965 * @param {Image} normalSprite normal state image 966 * @param {Image|Null} selectedSprite selected state image 967 * @param {Image|cc.Node|Null} three disabled state image OR target node 968 * @param {String|function|cc.Node|Null} four callback function name in string or actual function, OR target Node 969 * @param {String|function|Null} five callback function name in string or actual function 970 * @return {cc.MenuItemSprite} 971 * @example 972 * // Example 973 * var item = cc.MenuItemSprite.create(normalImage)//create a menu item from a sprite with no functionality 974 * 975 * var item = cc.MenuItemSprite.create(normalImage, selectedImage)//create a menu Item, nothing will happen when clicked 976 * 977 * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, disabledImage)//same above, but with disabled state image 978 * 979 * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, 'callback', targetNode)//create a menu item, when clicked runs targetNode.callback() 980 * 981 * var item = cc.MenuItemSprite.create(normalImage, SelectedImage, disabledImage, targetNode.callback, targetNode) 982 * //same as above, but with disabled image, and passing in callback function 983 */ 984 cc.MenuItemSprite.create = function (normalSprite, selectedSprite, three, four, five) { 985 return new cc.MenuItemSprite(normalSprite, selectedSprite, three, four, five || undefined); 986 }; 987 988 /** 989 * cc.MenuItemImage accepts images as items.<br/> 990 * The images has 3 different states:<br/> 991 * - unselected image<br/> 992 * - selected image<br/> 993 * - disabled image<br/> 994 * <br/> 995 * For best results try that all images are of the same size<br/> 996 * @class 997 * @extends cc.MenuItemSprite 998 */ 999 cc.MenuItemImage = cc.MenuItemSprite.extend(/** @lends cc.MenuItemImage# */{ 1000 1001 /** 1002 * @constructor 1003 * @param {string|null} normalImage 1004 * @param {string|null} selectedImage 1005 * @param {string|null} disabledImage 1006 * @param {function|string|null} callback 1007 * @param {cc.Node|null} target 1008 */ 1009 ctor: function (normalImage, selectedImage, three, four, five) { 1010 var normalSprite = null, 1011 selectedSprite = null, 1012 disabledSprite = null, 1013 callback = null, 1014 target = null; 1015 1016 if (normalImage === undefined) { 1017 cc.MenuItemSprite.prototype.ctor.call(this); 1018 } 1019 else { 1020 normalSprite = cc.Sprite.create(normalImage); 1021 selectedImage && 1022 (selectedSprite = cc.Sprite.create(selectedImage)); 1023 if (four === undefined) { 1024 callback = three; 1025 } 1026 else if (five === undefined) { 1027 callback = three; 1028 target = four; 1029 } 1030 else if (five) { 1031 disabledSprite = cc.Sprite.create(three); 1032 callback = four; 1033 target = five; 1034 } 1035 cc.MenuItemSprite.prototype.ctor.call(this, normalSprite, selectedSprite, disabledSprite, callback, target); 1036 } 1037 }, 1038 1039 /** 1040 * sets the sprite frame for the normal image 1041 * @param {cc.SpriteFrame} frame 1042 */ 1043 setNormalSpriteFrame: function (frame) { 1044 this.setNormalImage(cc.Sprite.create(frame)); 1045 }, 1046 1047 /** 1048 * sets the sprite frame for the selected image 1049 * @param {cc.SpriteFrame} frame 1050 */ 1051 setSelectedSpriteFrame: function (frame) { 1052 this.setSelectedImage(cc.Sprite.create(frame)); 1053 }, 1054 1055 /** 1056 * sets the sprite frame for the disabled image 1057 * @param {cc.SpriteFrame} frame 1058 */ 1059 setDisabledSpriteFrame: function (frame) { 1060 this.setDisabledImage(cc.Sprite.create(frame)); 1061 }, 1062 1063 /** 1064 * @param {string|null} normalImage 1065 * @param {string|null} selectedImage 1066 * @param {string|null} disabledImage 1067 * @param {function|string|null} callback 1068 * @param {cc.Node|null} target 1069 * @returns {boolean} 1070 */ 1071 initWithNormalImage: function (normalImage, selectedImage, disabledImage, callback, target) { 1072 var normalSprite = null; 1073 var selectedSprite = null; 1074 var disabledSprite = null; 1075 1076 if (normalImage) { 1077 normalSprite = cc.Sprite.create(normalImage); 1078 } 1079 if (selectedImage) { 1080 selectedSprite = cc.Sprite.create(selectedImage); 1081 } 1082 if (disabledImage) { 1083 disabledSprite = cc.Sprite.create(disabledImage); 1084 } 1085 return this.initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, callback, target); 1086 } 1087 }); 1088 1089 /** 1090 * creates a new menu item image 1091 * @param {String} normalImage file name for normal state 1092 * @param {String} selectedImage image for selected state 1093 * @param {String|cc.Node} three Disabled image OR callback function 1094 * @param {String|function|Null} [four] callback function, either name in string or pass the whole function OR the target 1095 * @param {cc.Node|String|function|Null} [five] cc.Node target to run callback when clicked 1096 * @return {cc.MenuItemImage} 1097 * @example 1098 * // Example 1099 * //create a dom menu item with normal and selected state, when clicked it will run the run function from gameScene object 1100 * var item = cc.MenuItemImage.create('normal.png', 'selected.png', 'run', gameScene) 1101 * 1102 * //same as above, but pass in the actual function and disabled image 1103 * var item = cc.MenuItemImage.create('normal.png', 'selected.png', 'disabled.png', gameScene.run, gameScene) 1104 */ 1105 cc.MenuItemImage.create = function (normalImage, selectedImage, three, four, five) { 1106 return new cc.MenuItemImage(normalImage, selectedImage, three, four, five); 1107 }; 1108 1109 1110 /** 1111 * A simple container class that "toggles" it's inner items<br/> 1112 * The inner items can be any MenuItem 1113 * @class 1114 * @extends cc.MenuItem 1115 * 1116 * @property {Array} subItems - Sub items 1117 * @property {Number} selectedIndex - Index of selected sub item 1118 */ 1119 cc.MenuItemToggle = cc.MenuItem.extend(/** @lends cc.MenuItemToggle# */{ 1120 subItems: null, 1121 1122 _selectedIndex: 0, 1123 _opacity: null, 1124 _color: null, 1125 1126 /** 1127 * @constructor 1128 * @example 1129 * // Example 1130 * //create a toggle item with 2 menu items (which you can then toggle between them later) 1131 * var toggler = new cc.MenuItemToggle( cc.MenuItemFont.create("On"), cc.MenuItemFont.create("Off"), this.callback, this) 1132 * //Note: the first param is the target, the second is the callback function, afterwards, you can pass in any number of menuitems 1133 * 1134 * //if you pass only 1 variable, then it must be a cc.MenuItem 1135 * var notYetToggler = new cc.MenuItemToggle(cc.MenuItemFont.create("On"));//it is useless right now, until you add more stuff to it 1136 * notYetToggler.addSubItem(cc.MenuItemFont.create("Off")); 1137 * //this is useful for constructing a toggler without a callback function (you wish to control the behavior from somewhere else) 1138 */ 1139 ctor: function (/*Multiple arguments follow*/) { 1140 var argc = arguments.length, callback, target; 1141 // passing callback. 1142 if (typeof arguments[argc - 2] === 'function') { 1143 callback = arguments[argc - 2]; 1144 target = arguments[argc - 1]; 1145 argc = argc - 2; 1146 } else if (typeof arguments[argc - 1] === 'function') { 1147 callback = arguments[argc - 1]; 1148 argc = argc - 1; 1149 } 1150 1151 cc.MenuItem.prototype.ctor.call(this, callback, target); 1152 this._selectedIndex = 0; 1153 this.subItems = []; 1154 this._opacity = 0; 1155 this._color = cc.color.WHITE; 1156 1157 if (argc > 0) { 1158 var locSubItems = this.subItems; 1159 locSubItems.length = 0; 1160 for (var i = 0; i < argc; i++) { 1161 if (arguments[i]) 1162 locSubItems.push(arguments[i]); 1163 } 1164 this._selectedIndex = cc.UINT_MAX; 1165 this.setSelectedIndex(0); 1166 this.setCascadeColorEnabled(true); 1167 this.setCascadeOpacityEnabled(true); 1168 } 1169 }, 1170 1171 /** 1172 * @return {Number} 1173 */ 1174 getOpacity: function () { 1175 return this._opacity; 1176 }, 1177 1178 /** 1179 * @param {Number} opacity 1180 */ 1181 setOpacity: function (opacity) { 1182 this._opacity = opacity; 1183 if (this.subItems && this.subItems.length > 0) { 1184 for (var it = 0; it < this.subItems.length; it++) { 1185 this.subItems[it].opacity = opacity; 1186 } 1187 } 1188 this._color.a = opacity; 1189 }, 1190 1191 /** 1192 * @return {cc.Color} 1193 */ 1194 getColor: function () { 1195 var locColor = this._color; 1196 return cc.color(locColor.r, locColor.g, locColor.b, locColor.a); 1197 }, 1198 1199 /** 1200 * @param {cc.Color} Color 1201 */ 1202 setColor: function (color) { 1203 var locColor = this._color; 1204 locColor.r = color.r; 1205 locColor.g = color.g; 1206 locColor.b = color.b; 1207 1208 if (this.subItems && this.subItems.length > 0) { 1209 for (var it = 0; it < this.subItems.length; it++) { 1210 this.subItems[it].setColor(color); 1211 } 1212 } 1213 1214 if (color.a !== undefined && !color.a_undefined) { 1215 this.setOpacity(color.a); 1216 } 1217 }, 1218 1219 /** 1220 * @return {Number} 1221 */ 1222 getSelectedIndex: function () { 1223 return this._selectedIndex; 1224 }, 1225 1226 /** 1227 * @param {Number} SelectedIndex 1228 */ 1229 setSelectedIndex: function (SelectedIndex) { 1230 if (SelectedIndex != this._selectedIndex) { 1231 this._selectedIndex = SelectedIndex; 1232 var currItem = this.getChildByTag(cc.CURRENT_ITEM); 1233 if (currItem) 1234 currItem.removeFromParent(false); 1235 1236 var item = this.subItems[this._selectedIndex]; 1237 this.addChild(item, 0, cc.CURRENT_ITEM); 1238 var w = item.width, h = item.height; 1239 this.width = w; 1240 this.height = h; 1241 item.setPosition(w / 2, h / 2); 1242 } 1243 }, 1244 1245 /** 1246 * similar to get children 1247 * @return {Array} 1248 */ 1249 getSubItems: function () { 1250 return this.subItems; 1251 }, 1252 1253 /** 1254 * @param {cc.MenuItem} subItems 1255 */ 1256 setSubItems: function (subItems) { 1257 this.subItems = subItems; 1258 }, 1259 1260 /** 1261 * @param {cc.MenuItem} args[0...last-2] the rest in the array are cc.MenuItems 1262 * @param {function|String} args[last-1] the second item in the args array is the callback 1263 * @param {cc.Node} args[last] the first item in the args array is a target 1264 * @return {Boolean} 1265 */ 1266 initWithItems: function (args) { 1267 var l = args.length; 1268 // passing callback. 1269 if (typeof args[args.length - 2] === 'function') { 1270 this.initWithCallback(args[args.length - 2], args[args.length - 1]); 1271 l = l - 2; 1272 } else if (typeof args[args.length - 1] === 'function') { 1273 this.initWithCallback(args[args.length - 1], null); 1274 l = l - 1; 1275 } else { 1276 this.initWithCallback(null, null); 1277 } 1278 1279 var locSubItems = this.subItems; 1280 locSubItems.length = 0; 1281 for (var i = 0; i < l; i++) { 1282 if (args[i]) 1283 locSubItems.push(args[i]); 1284 } 1285 this._selectedIndex = cc.UINT_MAX; 1286 this.setSelectedIndex(0); 1287 1288 this.cascadeColor = true; 1289 this.cascadeOpacity = true; 1290 1291 return true; 1292 }, 1293 1294 /** 1295 * @param {cc.MenuItem} item 1296 */ 1297 addSubItem: function (item) { 1298 this.subItems.push(item); 1299 }, 1300 1301 /** 1302 * activate the menu item 1303 */ 1304 activate: function () { 1305 // update index 1306 if (this._enabled) { 1307 var newIndex = (this._selectedIndex + 1) % this.subItems.length; 1308 this.setSelectedIndex(newIndex); 1309 } 1310 cc.MenuItem.prototype.activate.call(this); 1311 }, 1312 1313 /** 1314 * menu item is selected (runs callback) 1315 */ 1316 selected: function () { 1317 cc.MenuItem.prototype.selected.call(this); 1318 this.subItems[this._selectedIndex].selected(); 1319 }, 1320 1321 /** 1322 * menu item goes back to unselected state 1323 */ 1324 unselected: function () { 1325 cc.MenuItem.prototype.unselected.call(this); 1326 this.subItems[this._selectedIndex].unselected(); 1327 }, 1328 1329 /** 1330 * @param {Boolean} enabled 1331 */ 1332 setEnabled: function (enabled) { 1333 if (this._enabled != enabled) { 1334 cc.MenuItem.prototype.setEnabled.call(this, enabled); 1335 var locItems = this.subItems; 1336 if (locItems && locItems.length > 0) { 1337 for (var it = 0; it < locItems.length; it++) 1338 locItems[it].enabled = enabled; 1339 } 1340 } 1341 }, 1342 1343 /** 1344 * returns the selected item 1345 * @return {cc.MenuItem} 1346 */ 1347 selectedItem: function () { 1348 return this.subItems[this._selectedIndex]; 1349 }, 1350 1351 onEnter: function () { 1352 cc.Node.prototype.onEnter.call(this); 1353 this.setSelectedIndex(this._selectedIndex); 1354 } 1355 }); 1356 1357 var _p = cc.MenuItemToggle.prototype; 1358 1359 // Extended properties 1360 /** @expose */ 1361 _p.selectedIndex; 1362 cc.defineGetterSetter(_p, "selectedIndex", _p.getSelectedIndex, _p.setSelectedIndex); 1363 1364 1365 /** 1366 * create a simple container class that "toggles" it's inner items<br/> 1367 * The inner items can be any MenuItem 1368 * @return {cc.MenuItemToggle} 1369 * @example 1370 * // Example 1371 * 1372 * //create a toggle item with 2 menu items (which you can then toggle between them later) 1373 * var toggler = cc.MenuItemToggle.create( cc.MenuItemFont.create("On"), cc.MenuItemFont.create("Off"), this.callback, this) 1374 * //Note: the first param is the target, the second is the callback function, afterwards, you can pass in any number of menuitems 1375 * 1376 * //if you pass only 1 variable, then it must be a cc.MenuItem 1377 * var notYetToggler = cc.MenuItemToggle.create(cc.MenuItemFont.create("On"));//it is useless right now, until you add more stuff to it 1378 * notYetToggler.addSubItem(cc.MenuItemFont.create("Off")); 1379 * //this is useful for constructing a toggler without a callback function (you wish to control the behavior from somewhere else) 1380 */ 1381 cc.MenuItemToggle.create = function (/*Multiple arguments follow*/) { 1382 if ((arguments.length > 0) && (arguments[arguments.length - 1] == null)) 1383 cc.log("parameters should not be ending with null in Javascript"); 1384 var ret = new cc.MenuItemToggle(); 1385 ret.initWithItems(Array.prototype.slice.apply(arguments)); 1386 return ret; 1387 }; 1388