guiButtonCtrl.cc 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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::acceleratorKeyPress(U32)
  57. {
  58. if (!mActive)
  59. return;
  60. //set the bool
  61. mDepressed = true;
  62. if (mProfile->mTabable)
  63. setFirstResponder();
  64. //update
  65. setUpdate();
  66. }
  67. void GuiButtonCtrl::acceleratorKeyRelease(U32)
  68. {
  69. if (!mActive)
  70. return;
  71. if (mDepressed)
  72. {
  73. //set the bool
  74. mDepressed = false;
  75. //perform the action
  76. onAction();
  77. }
  78. //update
  79. setUpdate();
  80. }
  81. void GuiButtonCtrl::onTouchEnter(const GuiEvent &event)
  82. {
  83. if (!mActive)
  84. return;
  85. mMouseOver = true;
  86. if (isMouseLocked())
  87. {
  88. mDepressed = true;
  89. }
  90. else if (mActive && mProfile->mSoundButtonOver)
  91. {
  92. AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonOver);
  93. alxPlay(handle);
  94. }
  95. Con::executef(this, 1, "onTouchEnter");
  96. //update
  97. setUpdate();
  98. }
  99. void GuiButtonCtrl::onTouchLeave(const GuiEvent &)
  100. {
  101. if (!mActive)
  102. return;
  103. if (isMouseLocked())
  104. mDepressed = false;
  105. mouseUnlock();
  106. mMouseOver = false;
  107. Con::executef(this, 1, "onTouchLeave");
  108. //update
  109. setUpdate();
  110. }
  111. void GuiButtonCtrl::onTouchDown(const GuiEvent &event)
  112. {
  113. if (!mActive)
  114. return;
  115. mDepressed = true;
  116. if (mProfile->mCanKeyFocus)
  117. setFirstResponder();
  118. if (mProfile->mSoundButtonDown)
  119. {
  120. AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
  121. alxPlay(handle);
  122. }
  123. //lock the mouse
  124. mouseLock();
  125. // Execute callback
  126. char buf[3][32];
  127. dSprintf(buf[0], 32, "%d", event.modifier);
  128. dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
  129. dSprintf(buf[2], 32, "%d", event.mouseClickCount);
  130. Con::executef(this, 4, "onTouchDown", buf[0], buf[1], buf[2]);
  131. //update
  132. setUpdate();
  133. }
  134. void GuiButtonCtrl::onTouchUp(const GuiEvent &event)
  135. {
  136. if (!mActive)
  137. return;
  138. mouseUnlock();
  139. //if we released the mouse within this control, perform the action
  140. if (mDepressed)
  141. onAction();
  142. // Execute callback
  143. char buf[3][32];
  144. dSprintf(buf[0], 32, "%d", event.modifier);
  145. dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
  146. dSprintf(buf[2], 32, "%d", event.mouseClickCount);
  147. Con::executef(this, 4, "onTouchUp", buf[0], buf[1], buf[2]);
  148. mDepressed = false;
  149. //update
  150. setUpdate();
  151. }
  152. void GuiButtonCtrl::onRightMouseUp(const GuiEvent &event)
  153. {
  154. if (!mActive)
  155. return;
  156. Con::executef(this, 1, "onRightClick");
  157. Parent::onRightMouseUp(event);
  158. }
  159. bool GuiButtonCtrl::onKeyDown(const GuiEvent &event)
  160. {
  161. if (!mActive)
  162. return true;
  163. //see if the key down is a return or space or not
  164. if ((event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE)
  165. && event.modifier == 0)
  166. {
  167. if (mProfile->mSoundButtonDown)
  168. {
  169. AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
  170. alxPlay(handle);
  171. }
  172. return true;
  173. }
  174. //otherwise, pass the event to it's parent
  175. return Parent::onKeyDown(event);
  176. }
  177. bool GuiButtonCtrl::onKeyUp(const GuiEvent &event)
  178. {
  179. if (!mActive)
  180. return true;
  181. //see if the key down is a return or space or not
  182. if (mDepressed &&
  183. (event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE) &&
  184. event.modifier == 0)
  185. {
  186. onAction();
  187. return true;
  188. }
  189. //otherwise, pass the event to it's parent
  190. return Parent::onKeyUp(event);
  191. }
  192. void GuiButtonCtrl::onAction()
  193. {
  194. if (!mActive)
  195. return;
  196. setUpdate();
  197. if (isMethod("onClick"))
  198. Con::executef(this, 2, "onClick");
  199. Parent::onAction();
  200. }
  201. GuiControlState GuiButtonCtrl::getCurrentState()
  202. {
  203. if (!mActive)
  204. return GuiControlState::DisabledState;
  205. else if (mDepressed)
  206. return GuiControlState::SelectedState;
  207. else if (mMouseOver)
  208. return GuiControlState::HighlightState;
  209. else
  210. return GuiControlState::NormalState;
  211. }
  212. S32 GuiButtonCtrl::getBitmapIndex(const GuiControlState state)
  213. {
  214. if (state == GuiControlState::HighlightState)
  215. return 2;
  216. else if (state == GuiControlState::SelectedState)
  217. return 3;
  218. else if (state == GuiControlState::DisabledState)
  219. return 4;
  220. else
  221. return 1;
  222. }
  223. void GuiButtonCtrl::onRender(Point2I offset, const RectI& updateRect)
  224. {
  225. GuiControlState currentState = getCurrentState();
  226. RectI ctrlRect = applyMargins(offset, mBounds.extent, currentState, mProfile);
  227. renderUniversalRect(ctrlRect, mProfile, currentState, getFillColor(currentState), true);
  228. //Render Text
  229. dglSetBitmapModulation(mProfile->getFontColor(currentState));
  230. RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, currentState, mProfile);
  231. RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, mProfile);
  232. renderText(contentRect.point, contentRect.extent, mText, mProfile);
  233. //Render the childen
  234. renderChildControls(offset, contentRect, updateRect);
  235. }
  236. void GuiButtonCtrl::setScriptValue(const char *value)
  237. {
  238. // Update the console variable:
  239. if (mConsoleVariable[0])
  240. Con::setVariable(mConsoleVariable, value);
  241. setUpdate();
  242. }
  243. const char *GuiButtonCtrl::getScriptValue()
  244. {
  245. return StringTable->EmptyString;
  246. }
  247. void GuiButtonCtrl::onMessage(GuiControl *sender, S32 msg)
  248. {
  249. Parent::onMessage(sender, msg);
  250. }
  251. const ColorI& GuiButtonCtrl::getFillColor(const GuiControlState state)
  252. {
  253. if (state != mCurrentState)
  254. {
  255. //We have just switched states!
  256. mPreviousState = mCurrentState;
  257. mCurrentState = state;
  258. if (mCurrentState == GuiControlState::DisabledState || mPreviousState == GuiControlState::DisabledState)
  259. {
  260. mFluidFillColor.stopFluidAnimation();
  261. mFluidFillColor.set(mProfile->getFillColor(state));
  262. }
  263. else if (mCurrentState == GuiControlState::SelectedState || mPreviousState == GuiControlState::SelectedState)
  264. {
  265. mFluidFillColor.setEasingFunction(mEaseFillColorSL);
  266. mFluidFillColor.setAnimationLength(mEaseTimeFillColorSL);
  267. mFluidFillColor.startFluidAnimation(mProfile->getFillColor(state));
  268. }
  269. else if (mCurrentState == GuiControlState::HighlightState || mPreviousState == GuiControlState::HighlightState)
  270. {
  271. mFluidFillColor.setEasingFunction(mEaseFillColorHL);
  272. mFluidFillColor.setAnimationLength(mEaseTimeFillColorHL);
  273. mFluidFillColor.startFluidAnimation(mProfile->getFillColor(state));
  274. }
  275. else
  276. {
  277. //we should never get here...
  278. mFluidFillColor.stopFluidAnimation();
  279. mFluidFillColor.set(mProfile->getFillColor(state));
  280. }
  281. }
  282. if (mFluidFillColor.isAnimating() && !isProcessingTicks())
  283. {
  284. setProcessTicks(true);
  285. }
  286. if (!mFluidFillColor.isAnimating())
  287. {
  288. mFluidFillColor.set(mProfile->getFillColor(state));
  289. }
  290. return mFluidFillColor;
  291. }
  292. void GuiButtonCtrl::processTick()
  293. {
  294. bool shouldWeContinue = false;
  295. shouldWeContinue |= mFluidFillColor.processTick();
  296. if (!shouldWeContinue)
  297. {
  298. setProcessTicks(false);
  299. }
  300. }
  301. void GuiButtonCtrl::setControlProfile(GuiControlProfile *prof)
  302. {
  303. Parent::setControlProfile(prof);
  304. mCurrentState = mCurrentState == DisabledState ? NormalState : DisabledState;
  305. }