CCControlSlider.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * Copyright (c) 2012 cocos2d-x.org
  3. * http://www.cocos2d-x.org
  4. *
  5. * Copyright 2011 Yannick Loriot.
  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. * Converted to c++ / cocos2d-x by Angus C
  27. *
  28. */
  29. #include "CCControlSlider.h"
  30. #include "base/CCTouch.h"
  31. #include "base/CCDirector.h"
  32. NS_CC_EXT_BEGIN
  33. ControlSlider::ControlSlider()
  34. : _value(0.0f)
  35. , _minimumValue(0.0f)
  36. , _maximumValue(0.0f)
  37. , _minimumAllowedValue(0.0f)
  38. , _maximumAllowedValue(0.0f)
  39. , _thumbSprite(nullptr)
  40. , _selectedThumbSprite(nullptr)
  41. , _progressSprite(nullptr)
  42. , _backgroundSprite(nullptr)
  43. {
  44. }
  45. ControlSlider::~ControlSlider()
  46. {
  47. CC_SAFE_RELEASE(_thumbSprite);
  48. CC_SAFE_RELEASE(_selectedThumbSprite);
  49. CC_SAFE_RELEASE(_progressSprite);
  50. CC_SAFE_RELEASE(_backgroundSprite);
  51. }
  52. ControlSlider* ControlSlider::create(const char* bgFile, const char* progressFile, const char* thumbFile)
  53. {
  54. // Prepare background for slider
  55. Sprite *backgroundSprite = Sprite::create(bgFile);
  56. // Prepare progress for slider
  57. Sprite *progressSprite = Sprite::create(progressFile);
  58. // Prepare thumb (menuItem) for slider
  59. Sprite *thumbSprite = Sprite::create(thumbFile);
  60. return ControlSlider::create(backgroundSprite, progressSprite, thumbSprite);
  61. }
  62. ControlSlider* ControlSlider::create(const char* bgFile, const char* progressFile, const char* thumbFile,
  63. const char* selectedThumbSpriteFile)
  64. {
  65. // Prepare background for slider
  66. Sprite *backgroundSprite = Sprite::create(bgFile);
  67. // Prepare progress for slider
  68. Sprite *progressSprite = Sprite::create(progressFile);
  69. // Prepare thumb (menuItem) for slider
  70. Sprite *thumbSprite = Sprite::create(thumbFile);
  71. // Prepare selected thumb (menuItem) for slider
  72. Sprite *selectedThumbSprite = Sprite::create(selectedThumbSpriteFile);
  73. return ControlSlider::create(backgroundSprite, progressSprite, thumbSprite, selectedThumbSprite);
  74. }
  75. ControlSlider* ControlSlider::create(Sprite * backgroundSprite, Sprite* pogressSprite, Sprite* thumbSprite)
  76. {
  77. ControlSlider *pRet = new (std::nothrow) ControlSlider();
  78. pRet->initWithSprites(backgroundSprite, pogressSprite, thumbSprite);
  79. pRet->autorelease();
  80. return pRet;
  81. }
  82. ControlSlider* ControlSlider::create(Sprite * backgroundSprite, Sprite* pogressSprite, Sprite* thumbSprite,
  83. Sprite* selectedThumbSprite)
  84. {
  85. ControlSlider *pRet = new (std::nothrow) ControlSlider();
  86. pRet->initWithSprites(backgroundSprite, pogressSprite, thumbSprite, selectedThumbSprite);
  87. pRet->autorelease();
  88. return pRet;
  89. }
  90. bool ControlSlider::initWithSprites(Sprite * backgroundSprite, Sprite* progressSprite, Sprite* thumbSprite)
  91. {
  92. Sprite* selectedThumbSprite = Sprite::createWithSpriteFrame(thumbSprite->getSpriteFrame());
  93. selectedThumbSprite->setColor(Color3B::GRAY);
  94. return this->initWithSprites(backgroundSprite, progressSprite, thumbSprite, selectedThumbSprite);
  95. }
  96. bool ControlSlider::initWithSprites(Sprite * backgroundSprite, Sprite* progressSprite, Sprite* thumbSprite,
  97. Sprite* selectedThumbSprite)
  98. {
  99. if (Control::init())
  100. {
  101. CCASSERT(backgroundSprite, "Background sprite must be not nil");
  102. CCASSERT(progressSprite, "Progress sprite must be not nil");
  103. CCASSERT(thumbSprite, "Thumb sprite must be not nil");
  104. CCASSERT(selectedThumbSprite, "Thumb sprite must be not nil");
  105. setIgnoreAnchorPointForPosition(false);
  106. this->setBackgroundSprite(backgroundSprite);
  107. this->setProgressSprite(progressSprite);
  108. this->setThumbSprite(thumbSprite);
  109. this->setSelectedThumbSprite(selectedThumbSprite);
  110. // Defines the content size
  111. Rect maxRect = ControlUtils::RectUnion(backgroundSprite->getBoundingBox(), thumbSprite->getBoundingBox());
  112. setContentSize(Size(maxRect.size.width, maxRect.size.height));
  113. // Add the slider background
  114. _backgroundSprite->setAnchorPoint(Vec2(0.5f, 0.5f));
  115. _backgroundSprite->setPosition(this->getContentSize().width / 2, this->getContentSize().height / 2);
  116. addChild(_backgroundSprite);
  117. // Add the progress bar
  118. _progressSprite->setAnchorPoint(Vec2(0.0f, 0.5f));
  119. _progressSprite->setPosition(0.0f, this->getContentSize().height / 2);
  120. addChild(_progressSprite);
  121. // Add the slider thumb
  122. _thumbSprite->setPosition(0.0f, this->getContentSize().height / 2);
  123. addChild(_thumbSprite);
  124. _selectedThumbSprite->setPosition(0.0f, this->getContentSize().height / 2);
  125. _selectedThumbSprite->setVisible(false);
  126. addChild(_selectedThumbSprite);
  127. // Init default values
  128. _minimumValue = 0.0f;
  129. _maximumValue = 1.0f;
  130. setValue(_minimumValue);
  131. return true;
  132. }
  133. else
  134. {
  135. return false;
  136. }
  137. }
  138. void ControlSlider::setEnabled(bool enabled)
  139. {
  140. Control::setEnabled(enabled);
  141. if (_thumbSprite != nullptr)
  142. {
  143. _thumbSprite->setOpacity((enabled) ? 255 : 128);
  144. }
  145. }
  146. void ControlSlider::setValue(float value)
  147. {
  148. // set new value with sentinel
  149. if (value < _minimumValue)
  150. {
  151. value = _minimumValue;
  152. }
  153. if (value > _maximumValue)
  154. {
  155. value = _maximumValue;
  156. }
  157. _value = value;
  158. this->needsLayout();
  159. this->sendActionsForControlEvents(Control::EventType::VALUE_CHANGED);
  160. }
  161. void ControlSlider::setMinimumValue(float minimumValue)
  162. {
  163. _minimumValue=minimumValue;
  164. _minimumAllowedValue = minimumValue;
  165. if (_minimumValue >= _maximumValue)
  166. {
  167. _maximumValue = _minimumValue + 1.0f;
  168. }
  169. setValue(_value);
  170. }
  171. void ControlSlider::setMaximumValue(float maximumValue)
  172. {
  173. _maximumValue=maximumValue;
  174. _maximumAllowedValue = maximumValue;
  175. if (_maximumValue <= _minimumValue)
  176. {
  177. _minimumValue = _maximumValue - 1.0f;
  178. }
  179. setValue(_value);
  180. }
  181. bool ControlSlider::isTouchInside(Touch * touch)
  182. {
  183. Vec2 touchLocation = touch->getLocation();
  184. touchLocation = this->getParent()->convertToNodeSpace(touchLocation);
  185. Rect rect = this->getBoundingBox();
  186. rect.size.width += _thumbSprite->getContentSize().width;
  187. rect.origin.x -= _thumbSprite->getContentSize().width / 2;
  188. return rect.containsPoint(touchLocation);
  189. }
  190. Vec2 ControlSlider::locationFromTouch(Touch* touch)
  191. {
  192. Vec2 touchLocation = touch->getLocation(); // Get the touch position
  193. touchLocation = this->convertToNodeSpace(touchLocation); // Convert to the node space of this class
  194. if (touchLocation.x < 0)
  195. {
  196. touchLocation.x = 0;
  197. } else if (touchLocation.x > _backgroundSprite->getContentSize().width)
  198. {
  199. touchLocation.x = _backgroundSprite->getContentSize().width;
  200. }
  201. return touchLocation;
  202. }
  203. bool ControlSlider::onTouchBegan(Touch* touch, Event* /*pEvent*/)
  204. {
  205. if (!isTouchInside(touch) || !isEnabled() || !isVisible())
  206. {
  207. return false;
  208. }
  209. Vec2 location = locationFromTouch(touch);
  210. sliderBegan(location);
  211. return true;
  212. }
  213. void ControlSlider::onTouchMoved(Touch *pTouch, Event* /*pEvent*/)
  214. {
  215. Vec2 location = locationFromTouch(pTouch);
  216. sliderMoved(location);
  217. }
  218. void ControlSlider::onTouchEnded(Touch* /*pTouch*/, Event* /*pEvent*/)
  219. {
  220. sliderEnded(Vec2::ZERO);
  221. }
  222. void ControlSlider::needsLayout()
  223. {
  224. if (nullptr == _thumbSprite || nullptr == _selectedThumbSprite || nullptr == _backgroundSprite
  225. || nullptr == _progressSprite)
  226. {
  227. return;
  228. }
  229. // Update thumb position for new value
  230. float percent = (_value - _minimumValue) / (_maximumValue - _minimumValue);
  231. Vec2 pos = _thumbSprite->getPosition();
  232. pos.x = percent * _backgroundSprite->getContentSize().width;
  233. _thumbSprite->setPosition(pos);
  234. _selectedThumbSprite->setPosition(pos);
  235. // Stretches content proportional to newLevel
  236. Rect textureRect = _progressSprite->getTextureRect();
  237. textureRect = Rect(textureRect.origin.x, textureRect.origin.y, pos.x, textureRect.size.height);
  238. _progressSprite->setTextureRect(textureRect, _progressSprite->isTextureRectRotated(), textureRect.size);
  239. }
  240. void ControlSlider::sliderBegan(Vec2 location)
  241. {
  242. this->setSelected(true);
  243. _thumbSprite->setVisible(false);
  244. _selectedThumbSprite->setVisible(true);
  245. setValue(valueForLocation(location));
  246. }
  247. void ControlSlider::sliderMoved(Vec2 location)
  248. {
  249. setValue(valueForLocation(location));
  250. }
  251. void ControlSlider::sliderEnded(Vec2 /*location*/)
  252. {
  253. if (this->isSelected())
  254. {
  255. setValue(valueForLocation(_thumbSprite->getPosition()));
  256. }
  257. _thumbSprite->setVisible(true);
  258. _selectedThumbSprite->setVisible(false);
  259. this->setSelected(false);
  260. }
  261. float ControlSlider::valueForLocation(Vec2 location)
  262. {
  263. float percent = location.x/ _backgroundSprite->getContentSize().width;
  264. return MAX(MIN(_minimumValue + percent * (_maximumValue - _minimumValue), _maximumAllowedValue), _minimumAllowedValue);
  265. }
  266. NS_CC_EXT_END