PolyScreenEntity.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * PolyScreenEntity.cpp
  3. * TAU
  4. *
  5. * Created by Ivan Safrin on 3/13/08.
  6. * Copyright 2008 __MyCompanyName__. All rights reserved.
  7. *
  8. */
  9. #include "PolyScreenEntity.h"
  10. using namespace Polycode;
  11. ScreenEntity::ScreenEntity() : Entity(), EventDispatcher() {
  12. color = new Color(1.0f,1.0f,1.0f,1.0f);
  13. width = 1;
  14. height = 1;
  15. hitwidth = 1;
  16. hitheight = 1;
  17. backfaceCulled = false;
  18. positionMode = POSITION_TOPLEFT;
  19. mouseOver = false;
  20. isDragged = false;
  21. dragOffsetX = 0;
  22. dragOffsetY = 0;
  23. parentEntity = NULL;
  24. zindex = 0;
  25. depthWrite = false;
  26. depthTest = false;
  27. focusable = false;
  28. hasFocus = false;
  29. focusChildren = false;
  30. focusedChild = NULL;
  31. blockMouseInput = false;
  32. snapToPixels = false;
  33. lastClickTicks = 0;
  34. dragLimits = NULL;
  35. xmouse = 0;
  36. ymouse = 0;
  37. }
  38. void ScreenEntity::focusNextChild() {
  39. int j = 0;
  40. if(focusedChild) {
  41. for(int i=0; i < children.size(); i++) {
  42. if(children[i] == focusedChild)
  43. j = i;
  44. }
  45. }
  46. for(int i=0; i < children.size(); i++) {
  47. if(((ScreenEntity*)children[j])->isFocusable() && children[j] != focusedChild) {
  48. focusChild(((ScreenEntity*)children[j]));
  49. return;
  50. }
  51. j++;
  52. if(j == children.size())
  53. j = 0;
  54. }
  55. }
  56. Number ScreenEntity::getRotation() {
  57. return this->getRoll();
  58. }
  59. void ScreenEntity::focusChild(ScreenEntity *child) {
  60. if(focusedChild != NULL) {
  61. focusedChild->onLoseFocus();
  62. focusedChild->hasFocus = false;
  63. }
  64. focusedChild = child;
  65. focusedChild->hasFocus = true;
  66. focusedChild->onGainFocus();
  67. }
  68. bool ScreenEntity::isFocusable() {
  69. return focusable;
  70. }
  71. void ScreenEntity::startDrag(Number xOffset, Number yOffset) {
  72. isDragged = true;
  73. dragOffsetX = xOffset;
  74. dragOffsetY = yOffset;
  75. }
  76. void ScreenEntity::stopDrag() {
  77. isDragged = false;
  78. }
  79. ScreenEntity::~ScreenEntity() {
  80. }
  81. void ScreenEntity::setBlendingMode(int newBlendingMode) {
  82. blendingMode = newBlendingMode;
  83. }
  84. void ScreenEntity::setPosition(Number x, Number y) {
  85. position.x = x;
  86. position.y = y;
  87. matrixDirty = true;
  88. }
  89. void ScreenEntity::setScale(Number x, Number y) {
  90. scale.x = x;
  91. scale.y = y;
  92. matrixDirty = true;
  93. }
  94. Number ScreenEntity::getWidth() {
  95. return width;
  96. }
  97. Number ScreenEntity::getHeight() {
  98. return height;
  99. }
  100. bool ScreenEntity::hitTest(Number x, Number y) {
  101. bool retVal = false;
  102. // Logger::log("hittest %f,%f in %f %f %f %f\n",x, y, position.x, position.y, hitwidth, hitheight);
  103. switch(positionMode) {
  104. case ScreenEntity::POSITION_TOPLEFT:
  105. if(x > position.x && x < (position.x + hitwidth)
  106. && y > position.y && y < (position.y + hitheight))
  107. retVal = true;
  108. break;
  109. case ScreenEntity::POSITION_CENTER:
  110. if(x > (position.x - hitwidth/2.0f) && x < (position.x + hitwidth/2.0f)
  111. && y > (position.y - hitheight/2.0f) && y < (position.y + hitheight/2.0f))
  112. retVal = true;
  113. break;
  114. }
  115. return retVal;
  116. }
  117. void ScreenEntity::setPositionMode(int newPositionMode) {
  118. positionMode = newPositionMode;
  119. }
  120. void ScreenEntity::_onKeyDown(TAUKey key, wchar_t charCode) {
  121. onKeyDown(key, charCode);
  122. for(int i=0;i<children.size();i++) {
  123. ((ScreenEntity*)children[i])->_onKeyDown(key, charCode);
  124. }
  125. }
  126. void ScreenEntity::_onKeyUp(TAUKey key, wchar_t charCode) {
  127. onKeyUp(key, charCode);
  128. for(int i=0;i<children.size();i++) {
  129. ((ScreenEntity*)children[i])->_onKeyUp(key, charCode);
  130. }
  131. }
  132. void ScreenEntity::setDragLimits(Polycode::Rectangle rect) {
  133. if(!dragLimits)
  134. dragLimits = new Polycode::Rectangle();
  135. dragLimits->x = rect.x;
  136. dragLimits->y = rect.y;
  137. dragLimits->w = rect.w;
  138. dragLimits->h = rect.h;
  139. }
  140. void ScreenEntity::clearDragLimits() {
  141. delete dragLimits;
  142. dragLimits = NULL;
  143. }
  144. void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp) {
  145. if(isDragged) {
  146. setPosition(x-dragOffsetX,y-dragOffsetY);
  147. if(dragLimits) {
  148. if(position.x < dragLimits->x)
  149. position.x = dragLimits->x;
  150. if(position.x > dragLimits->x + dragLimits->w)
  151. position.x = dragLimits->x + dragLimits->w;
  152. if(position.y < dragLimits->y)
  153. position.y = dragLimits->y;
  154. if(position.y > dragLimits->y + dragLimits->h)
  155. position.y = dragLimits->y + dragLimits->h;
  156. }
  157. }
  158. xmouse = x-position.x;
  159. ymouse = y-position.y;
  160. onMouseMove(x,y);
  161. if(enabled) {
  162. if(hitTest(x,y)) {
  163. dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEMOVE);
  164. if(!mouseOver) {
  165. dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEOVER);
  166. mouseOver = true;
  167. }
  168. } else {
  169. if(mouseOver) {
  170. dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEOUT);
  171. mouseOver = false;
  172. }
  173. }
  174. }
  175. if(enabled) {
  176. for(int i=0;i<children.size();i++) {
  177. ((ScreenEntity*)children[i])->_onMouseMove(x-position.x,y-position.y, timestamp);
  178. }
  179. }
  180. }
  181. bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp) {
  182. bool retVal = false;
  183. if(hitTest(x,y) && enabled) {
  184. onMouseUp(x,y);
  185. InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
  186. inputEvent->mouseButton = mouseButton;
  187. dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP);
  188. retVal = true;
  189. } else {
  190. InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
  191. inputEvent->mouseButton = mouseButton;
  192. dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP_OUTSIDE);
  193. }
  194. if(enabled) {
  195. for(int i=0;i<children.size();i++) {
  196. ((ScreenEntity*)children[i])->_onMouseUp(x-position.x,y-position.y, mouseButton, timestamp);
  197. }
  198. }
  199. return retVal;
  200. }
  201. void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp) {
  202. bool doTest = true;
  203. if(hasMask) {
  204. if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
  205. doTest = false;
  206. }
  207. }
  208. if(doTest) {
  209. if(hitTest(x,y) && enabled) {
  210. onMouseWheelUp(x,y);
  211. dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEWHEEL_UP);
  212. }
  213. if(enabled) {
  214. for(int i=children.size()-1;i>=0;i--) {
  215. ((ScreenEntity*)children[i])->_onMouseWheelUp(x-position.x,y-position.y, timestamp);
  216. if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
  217. if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
  218. break;
  219. }
  220. }
  221. }
  222. }
  223. }
  224. void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp) {
  225. bool doTest = true;
  226. if(hasMask) {
  227. if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
  228. doTest = false;
  229. }
  230. }
  231. if(doTest) {
  232. if(hitTest(x,y) && enabled) {
  233. onMouseWheelDown(x,y);
  234. dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEWHEEL_DOWN);
  235. }
  236. if(enabled) {
  237. for(int i=children.size()-1;i>=0;i--) {
  238. ((ScreenEntity*)children[i])->_onMouseWheelDown(x-position.x,y-position.y, timestamp);
  239. if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
  240. if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
  241. break;
  242. }
  243. }
  244. }
  245. }
  246. }
  247. bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timestamp) {
  248. bool retVal = false;
  249. bool doTest = true;
  250. if(hasMask) {
  251. if(!((ScreenEntity*)maskEntity)->hitTest(x,y)) {
  252. doTest = false;
  253. }
  254. }
  255. if(doTest) {
  256. if(hitTest(x,y) && enabled) {
  257. onMouseDown(x,y);
  258. InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
  259. inputEvent->mouseButton = mouseButton;
  260. dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEDOWN);
  261. if(timestamp - lastClickTicks < 400) {
  262. InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
  263. inputEvent->mouseButton = mouseButton;
  264. dispatchEvent(inputEvent, InputEvent::EVENT_DOUBLECLICK);
  265. }
  266. lastClickTicks = timestamp;
  267. retVal = true;
  268. }
  269. if(enabled) {
  270. for(int i=children.size()-1;i>=0;i--) {
  271. ((ScreenEntity*)children[i])->_onMouseDown(x-position.x,y-position.y, mouseButton, timestamp);
  272. if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
  273. if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
  274. break;
  275. }
  276. }
  277. }
  278. }
  279. return retVal;
  280. }
  281. void ScreenEntity::setRotation(Number rotation) {
  282. setRoll(rotation);
  283. }
  284. Vector2 ScreenEntity::getPosition2D() {
  285. return Vector2(position.x, position.y);
  286. }
  287. Matrix4 ScreenEntity::buildPositionMatrix() {
  288. Matrix4 posMatrix;
  289. switch(positionMode) {
  290. case POSITION_TOPLEFT:
  291. // renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
  292. posMatrix.m[3][0] = (position.x+floor(width/2.0f)*scale.x)*matrixAdj;
  293. posMatrix.m[3][1] = (position.y+floor(height/2.0f)*scale.y)*matrixAdj;
  294. posMatrix.m[3][2] = position.z*matrixAdj;
  295. break;
  296. case POSITION_CENTER:
  297. posMatrix.m[3][0] = position.x*matrixAdj;
  298. posMatrix.m[3][1] = position.y*matrixAdj;
  299. posMatrix.m[3][2] = position.z*matrixAdj;
  300. break;
  301. }
  302. if(snapToPixels) {
  303. posMatrix.m[3][0] = round(posMatrix.m[3][0]);
  304. posMatrix.m[3][1] = round(posMatrix.m[3][1]);
  305. posMatrix.m[3][2] = round(posMatrix.m[3][2]);
  306. }
  307. return posMatrix;
  308. }
  309. void ScreenEntity::adjustMatrixForChildren() {
  310. if(positionMode == POSITION_TOPLEFT)
  311. renderer->translate2D(-floor(width/2.0f)*scale.x, -floor(height/2.0f)*scale.y);
  312. }
  313. /*
  314. void ScreenEntity::transformAndRender() {
  315. Update();
  316. if(!renderer || !visible)
  317. return;
  318. renderer->pushMatrix();
  319. switch(positionMode) {
  320. case POSITION_TOPLEFT:
  321. renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
  322. break;
  323. case POSITION_CENTER:
  324. renderer->translate2D(position.x, position.y);
  325. break;
  326. }
  327. renderer->scale2D(scale);
  328. renderer->rotate2D(rotation);
  329. if(parentEntity) {
  330. Color combined = getCombinedColor();
  331. renderer->setVertexColor(combined.r,combined.g,combined.b,combined.a);
  332. } else {
  333. renderer->setVertexColor(color.r,color.g,color.b,color.a);
  334. }
  335. renderer->setBlendingMode(blendingMode);
  336. Render();
  337. if(positionMode == POSITION_TOPLEFT)
  338. renderer->translate2D(-ceil(width/2.0f)*scale->x, -ceil(height/2.0f)*scale->y);
  339. renderChildren();
  340. renderer->popMatrix();
  341. }
  342. */