guiButtonCtrl.cc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "console/console.h"
  23. #include "graphics/dgl.h"
  24. #include "console/consoleTypes.h"
  25. #include "platform/platformAudio.h"
  26. #include "gui/guiCanvas.h"
  27. #include "gui/buttons/guiButtonCtrl.h"
  28. #include "gui/guiDefaultControlRender.h"
  29. #include "guiButtonCtrl_ScriptBinding.h"
  30. IMPLEMENT_CONOBJECT(GuiButtonCtrl);
  31. GuiButtonCtrl::GuiButtonCtrl()
  32. {
  33. mDepressed = false;
  34. mMouseOver = false;
  35. mActive = true;
  36. mBounds.extent.set(140, 30);
  37. mText = StringTable->insert("Button");
  38. mTextID = StringTable->EmptyString;
  39. //fill color
  40. mEaseFillColorHL = EasingFunction::Linear;
  41. mEaseFillColorSL = EasingFunction::Linear;
  42. mEaseTimeFillColorHL = 500;
  43. mEaseTimeFillColorSL = 0;
  44. //control state
  45. mPreviousState = GuiControlState::DisabledState;
  46. mCurrentState = GuiControlState::DisabledState;
  47. }
  48. void GuiButtonCtrl::initPersistFields()
  49. {
  50. Parent::initPersistFields();
  51. addField("easeFillColorHL", TypeEnum, Offset(mEaseFillColorHL, GuiButtonCtrl), 1, &gEasingTable);
  52. addField("easeFillColorSL", TypeEnum, Offset(mEaseFillColorSL, GuiButtonCtrl), 1, &gEasingTable);
  53. addField("easeTimeFillColorHL", TypeS32, Offset(mEaseTimeFillColorHL, GuiButtonCtrl));
  54. addField("easeTimeFillColorSL", TypeS32, Offset(mEaseTimeFillColorSL, GuiButtonCtrl));
  55. }
  56. void GuiButtonCtrl::setActive(bool value)
  57. {
  58. Parent::setActive(value);
  59. if (!value)
  60. {
  61. mDepressed = false;
  62. mMouseOver = false;
  63. }
  64. }
  65. void GuiButtonCtrl::acceleratorKeyPress(U32)
  66. {
  67. if (!mActive)
  68. return;
  69. //set the bool
  70. mDepressed = true;
  71. if (mProfile->mTabable)
  72. setFirstResponder();
  73. //update
  74. setUpdate();
  75. }
  76. void GuiButtonCtrl::acceleratorKeyRelease(U32)
  77. {
  78. if (!mActive)
  79. return;
  80. if (mDepressed)
  81. {
  82. //set the bool
  83. mDepressed = false;
  84. //perform the action
  85. onAction();
  86. }
  87. //update
  88. setUpdate();
  89. }
  90. void GuiButtonCtrl::onTouchEnter(const GuiEvent &event)
  91. {
  92. if (!mActive)
  93. return;
  94. mMouseOver = true;
  95. if (isMouseLocked())
  96. {
  97. mDepressed = true;
  98. }
  99. else if (mActive && mProfile->mSoundButtonOver)
  100. {
  101. AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonOver);
  102. alxPlay(handle);
  103. }
  104. Con::executef(this, 1, "onTouchEnter");
  105. //update
  106. setUpdate();
  107. }
  108. void GuiButtonCtrl::onTouchLeave(const GuiEvent &)
  109. {
  110. if (!mActive)
  111. return;
  112. if (isMouseLocked())
  113. mDepressed = false;
  114. mouseUnlock();
  115. mMouseOver = false;
  116. Con::executef(this, 1, "onTouchLeave");
  117. //update
  118. setUpdate();
  119. }
  120. void GuiButtonCtrl::onTouchDown(const GuiEvent &event)
  121. {
  122. if (!mActive)
  123. return;
  124. mDepressed = true;
  125. if (mProfile->mCanKeyFocus)
  126. setFirstResponder();
  127. if (mProfile->mSoundButtonDown)
  128. {
  129. AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
  130. alxPlay(handle);
  131. }
  132. //lock the mouse
  133. mouseLock();
  134. // Execute callback
  135. char buf[3][32];
  136. dSprintf(buf[0], 32, "%d", event.modifier);
  137. dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
  138. dSprintf(buf[2], 32, "%d", event.mouseClickCount);
  139. Con::executef(this, 4, "onTouchDown", buf[0], buf[1], buf[2]);
  140. //update
  141. setUpdate();
  142. }
  143. void GuiButtonCtrl::onTouchUp(const GuiEvent &event)
  144. {
  145. if (!mActive)
  146. return;
  147. mouseUnlock();
  148. //if we released the mouse within this control, perform the action
  149. if (mDepressed)
  150. onAction();
  151. // Execute callback
  152. char buf[3][32];
  153. dSprintf(buf[0], 32, "%d", event.modifier);
  154. dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
  155. dSprintf(buf[2], 32, "%d", event.mouseClickCount);
  156. Con::executef(this, 4, "onTouchUp", buf[0], buf[1], buf[2]);
  157. mDepressed = false;
  158. //update
  159. setUpdate();
  160. }
  161. void GuiButtonCtrl::onRightMouseUp(const GuiEvent &event)
  162. {
  163. if (!mActive)
  164. return;
  165. Con::executef(this, 1, "onRightClick");
  166. Parent::onRightMouseUp(event);
  167. }
  168. bool GuiButtonCtrl::onKeyDown(const GuiEvent &event)
  169. {
  170. if (!mActive)
  171. return true;
  172. //see if the key down is a return or space or not
  173. if ((event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE)
  174. && event.modifier == 0)
  175. {
  176. if (mProfile->mSoundButtonDown)
  177. {
  178. AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
  179. alxPlay(handle);
  180. }
  181. return true;
  182. }
  183. //otherwise, pass the event to it's parent
  184. return Parent::onKeyDown(event);
  185. }
  186. bool GuiButtonCtrl::onKeyUp(const GuiEvent &event)
  187. {
  188. if (!mActive)
  189. return true;
  190. //see if the key down is a return or space or not
  191. if (mDepressed &&
  192. (event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE) &&
  193. event.modifier == 0)
  194. {
  195. onAction();
  196. return true;
  197. }
  198. //otherwise, pass the event to it's parent
  199. return Parent::onKeyUp(event);
  200. }
  201. void GuiButtonCtrl::onAction()
  202. {
  203. if (!mActive)
  204. return;
  205. setUpdate();
  206. if (isMethod("onClick"))
  207. Con::executef(this, 2, "onClick");
  208. Parent::onAction();
  209. }
  210. GuiControlState GuiButtonCtrl::getCurrentState()
  211. {
  212. if (!mActive)
  213. return GuiControlState::DisabledState;
  214. else if (mDepressed)
  215. return GuiControlState::SelectedState;
  216. else if (mMouseOver)
  217. return GuiControlState::HighlightState;
  218. else
  219. return GuiControlState::NormalState;
  220. }
  221. S32 GuiButtonCtrl::getBitmapIndex(const GuiControlState state)
  222. {
  223. if (state == GuiControlState::HighlightState)
  224. return 2;
  225. else if (state == GuiControlState::SelectedState)
  226. return 3;
  227. else if (state == GuiControlState::DisabledState)
  228. return 4;
  229. else
  230. return 1;
  231. }
  232. void GuiButtonCtrl::onRender(Point2I offset, const RectI& updateRect)
  233. {
  234. GuiControlState currentState = getCurrentState();
  235. RectI ctrlRect = applyMargins(offset, mBounds.extent, currentState, mProfile);
  236. renderUniversalRect(ctrlRect, mProfile, currentState, getFillColor(currentState), true);
  237. //Render Text
  238. dglSetBitmapModulation(getFontColor(mProfile, currentState));
  239. RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, currentState, mProfile);
  240. RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, mProfile);
  241. renderText(contentRect.point, contentRect.extent, mText, mProfile);
  242. //Render the childen
  243. renderChildControls(offset, contentRect, updateRect);
  244. }
  245. void GuiButtonCtrl::setScriptValue(const char *value)
  246. {
  247. // Update the console variable:
  248. if (mConsoleVariable[0])
  249. Con::setVariable(mConsoleVariable, value);
  250. setUpdate();
  251. }
  252. const char *GuiButtonCtrl::getScriptValue()
  253. {
  254. return StringTable->EmptyString;
  255. }
  256. void GuiButtonCtrl::onMessage(GuiControl *sender, S32 msg)
  257. {
  258. Parent::onMessage(sender, msg);
  259. }
  260. const ColorI& GuiButtonCtrl::getFillColor(const GuiControlState state)
  261. {
  262. if (state != mCurrentState)
  263. {
  264. //We have just switched states!
  265. mPreviousState = mCurrentState;
  266. mCurrentState = state;
  267. if (mCurrentState == GuiControlState::DisabledState || mPreviousState == GuiControlState::DisabledState)
  268. {
  269. mFluidFillColor.stopFluidAnimation();
  270. mFluidFillColor.set(mProfile->getFillColor(state));
  271. }
  272. else if (mCurrentState == GuiControlState::SelectedState || mPreviousState == GuiControlState::SelectedState)
  273. {
  274. mFluidFillColor.setEasingFunction(mEaseFillColorSL);
  275. mFluidFillColor.setAnimationLength(mEaseTimeFillColorSL);
  276. mFluidFillColor.startFluidAnimation(mProfile->getFillColor(state));
  277. }
  278. else if (mCurrentState == GuiControlState::HighlightState || mPreviousState == GuiControlState::HighlightState)
  279. {
  280. mFluidFillColor.setEasingFunction(mEaseFillColorHL);
  281. mFluidFillColor.setAnimationLength(mEaseTimeFillColorHL);
  282. mFluidFillColor.startFluidAnimation(mProfile->getFillColor(state));
  283. }
  284. else
  285. {
  286. //we should never get here...
  287. mFluidFillColor.stopFluidAnimation();
  288. mFluidFillColor.set(mProfile->getFillColor(state));
  289. }
  290. }
  291. if (mFluidFillColor.isAnimating() && !isProcessingTicks())
  292. {
  293. setProcessTicks(true);
  294. }
  295. if (!mFluidFillColor.isAnimating())
  296. {
  297. mFluidFillColor.set(mProfile->getFillColor(state));
  298. }
  299. return mFluidFillColor;
  300. }
  301. void GuiButtonCtrl::processTick()
  302. {
  303. bool shouldWeContinue = false;
  304. shouldWeContinue |= mFluidFillColor.processTick();
  305. if (!shouldWeContinue)
  306. {
  307. setProcessTicks(false);
  308. }
  309. }
  310. void GuiButtonCtrl::setControlProfile(GuiControlProfile *prof)
  311. {
  312. Parent::setControlProfile(prof);
  313. mCurrentState = mCurrentState == DisabledState ? NormalState : DisabledState;
  314. }