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