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