1 /** 2 * Copyright (c) 2012 cocos2d-x.org 3 * http://www.cocos2d-x.org 4 * 5 * Copyright 2012 Yannick Loriot. All rights reserved. 6 * http://yannickloriot.com 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 28 /** 29 * CCControlPotentiometer Potentiometer control for Cocos2D. 30 * @class 31 * @extends cc.Control 32 */ 33 cc.ControlPotentiometer = cc.Control.extend({ 34 _thumbSprite:null, 35 _progressTimer:null, 36 _previousLocation:null, 37 /** Contains the receiver’s current value. */ 38 _value:0, 39 /** Contains the minimum value of the receiver. 40 * The default value of this property is 0.0. */ 41 _minimumValue:0, 42 /** Contains the maximum value of the receiver. 43 * The default value of this property is 1.0. */ 44 _maximumValue:1, 45 46 /** 47 * 48 * @param {cc.Sprite} trackSprite 49 * @param {cc.ProgressTimer} progressTimer 50 * @param {cc.Sprite} thumbSprite 51 * @return {Boolean} 52 */ 53 initWithTrackSprite_ProgressTimer_ThumbSprite:function (trackSprite, progressTimer, thumbSprite) { 54 if (this.init()) { 55 this.setTouchEnabled(true); 56 57 this.setProgressTimer(progressTimer); 58 this.setThumbSprite(thumbSprite); 59 this._thumbSprite.setPosition(progressTimer.getPosition()); 60 61 this.addChild(thumbSprite, 2); 62 this.addChild(progressTimer, 1); 63 this.addChild(trackSprite); 64 65 this.setContentSize(trackSprite.getContentSize()); 66 67 // Init default values 68 this._minimumValue = 0.0; 69 this._maximumValue = 1.0; 70 this.setValue(this._minimumValue); 71 return true; 72 } 73 return false; 74 }, 75 76 setEnabled:function (enabled) { 77 this.setEnabled(enabled); 78 if (this._thumbSprite != NULL) { 79 this._thumbSprite.setOpacity((enabled) ? 255 : 128); 80 } 81 }, 82 83 setValue:function (value) { 84 // set new value with sentinel 85 if (value < this._minimumValue) { 86 value = this._minimumValue; 87 } 88 89 if (value > this._maximumValue) { 90 value = this._maximumValue; 91 } 92 93 this._value = value; 94 95 // Update thumb and progress position for new value 96 var percent = (value - this._minimumValue) / (this._maximumValue - this._minimumValue); 97 this._progressTimer.setPercentage(percent * 100.0); 98 this._thumbSprite.setRotation(percent * 360.0); 99 100 this.sendActionsForControlEvents(cc.CONTROL_EVENT_VALUECHANGED); 101 }, 102 103 getValue:function () { 104 return this._value; 105 }, 106 107 setMinimumValue:function (minimumValue) { 108 this._minimumValue = minimumValue; 109 110 if (this._minimumValue >= this._maximumValue) { 111 this._maximumValue = this._minimumValue + 1.0; 112 } 113 114 this.setValue(this._maximumValue); 115 }, 116 117 getMinimumValue:function () { 118 return this._minimumValue; 119 }, 120 121 setMaximumValue:function (maximumValue) { 122 this._maximumValue = maximumValue; 123 124 if (this._maximumValue <= this._minimumValue) { 125 this._minimumValue = this._maximumValue - 1.0; 126 } 127 128 this.setValue(this._minimumValue); 129 }, 130 131 getMaximumValue:function () { 132 return this._maximumValue; 133 }, 134 135 isTouchInside:function (touch) { 136 var touchLocation = this.getTouchLocation(touch); 137 138 var distance = this.distanceBetweenPointAndPoint(this._progressTimer.getPosition(), touchLocation); 139 140 return distance < Math.min(this.getContentSize().width / 2, this.getContentSize().height / 2); 141 }, 142 143 onTouchBegan:function (touch, event) { 144 if (!this.isTouchInside(touch) || !this.isEnabled() || !this.isVisible()) { 145 return false; 146 } 147 148 this._previousLocation = this.getTouchLocation(touch); 149 150 this.potentiometerBegan(this._previousLocation); 151 152 return true; 153 }, 154 155 onTouchMoved:function (touch, event) { 156 var location = this.getTouchLocation(touch); 157 158 this.potentiometerMoved(location); 159 }, 160 161 onTouchEnded:function (touch, event) { 162 this.potentiometerEnded(cc.p(0, 0)); 163 }, 164 165 /** 166 * the distance between the point1 and point2 167 * @param {cc.Point} point1 168 * @param {cc.Point} point2 169 * @return {Number} 170 */ 171 distanceBetweenPointAndPoint:function (point1, point2) { 172 var dx = point1.x - point2.x; 173 var dy = point1.y - point2.y; 174 return Math.sqrt(dx * dx + dy * dy); 175 }, 176 177 /** 178 * the angle in degree between line1 and line2. 179 * @param {cc.Point} beginLineA 180 * @param {cc.Point} endLineA 181 * @param {cc.Point} beginLineB 182 * @param {cc.Point} endLineB 183 * @return {Number} 184 */ 185 angleInDegreesBetweenLineFromPoint_toPoint_toLineFromPoint_toPoint:function (beginLineA, endLineA, beginLineB, endLineB) { 186 var a = endLineA.x - beginLineA.x; 187 var b = endLineA.y - beginLineA.y; 188 var c = endLineB.x - beginLineB.x; 189 var d = endLineB.y - beginLineB.y; 190 191 var atanA = Math.atan2(a, b); 192 var atanB = Math.atan2(c, d); 193 194 // convert radiants to degrees 195 return (atanA - atanB) * 180 / Math.PI; 196 }, 197 198 potentiometerBegan:function (location) { 199 this.setSelected(true); 200 this.getThumbSprite().setColor(cc.gray()); 201 }, 202 203 potentiometerMoved:function (location) { 204 var angle = this.angleInDegreesBetweenLineFromPoint_toPoint_toLineFromPoint_toPoint(this._progressTimer.getPosition(), location, this._progressTimer.getPosition(), this._previousLocation); 205 206 // fix value, if the 12 o'clock position is between location and previousLocation 207 if (angle > 180) { 208 angle -= 360; 209 } 210 else if (angle < -180) { 211 angle += 360; 212 } 213 214 this.setValue(this._value + angle / 360.0 * (this._maximumValue - this._minimumValue)); 215 216 this._previousLocation = location; 217 }, 218 219 potentiometerEnded:function (location) { 220 this.getThumbSprite().setColor(cc.white()); 221 this.setSelected(false); 222 }, 223 setThumbSprite:function (sprite) { 224 this._thumbSprite = sprite; 225 }, 226 getThumbSprite:function () { 227 return this._thumbSprite; 228 }, 229 setProgressTimer:function (sprite) { 230 this._progressTimer = sprite; 231 }, 232 getProgressTimer:function () { 233 return this._progressTimer; 234 }, 235 setPreviousLocation:function (point) { 236 this._previousLocation = point; 237 }, 238 getPreviousLocation:function () { 239 return this._previousLocation; 240 } 241 }); 242 243 cc.ControlPotentiometer.create = function (backgroundFile, progressFile, thumbFile) { 244 var pRet = new cc.ControlPotentiometer(); 245 if (pRet) { 246 // Prepare track for potentiometer 247 var backgroundSprite = cc.Sprite.create(backgroundFile); 248 249 // Prepare thumb for potentiometer 250 var thumbSprite = cc.Sprite.create(thumbFile); 251 252 // Prepare progress for potentiometer 253 var progressTimer = cc.ProgressTimer.create(cc.Sprite.create(progressFile)); 254 if (pRet.initWithTrackSprite_ProgressTimer_ThumbSprite(backgroundSprite, progressTimer, thumbSprite)) { 255 return pRet; 256 } 257 } 258 return null; 259 };