CCEGLView.js 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  1. /****************************************************************************
  2. Copyright (c) 2010-2012 cocos2d-x.org
  3. Copyright (c) 2008-2010 Ricardo Quesada
  4. Copyright (c) 2011 Zynga Inc.
  5. http://www.cocos2d-x.org
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  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 FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. ****************************************************************************/
  22. cc.RESOLUTION_POLICY = {
  23. // The entire application is visible in the specified area without trying to preserve the original aspect ratio.
  24. // Distortion can occur, and the application may appear stretched or compressed.
  25. EXACT_FIT: 0,
  26. // The entire application fills the specified area, without distortion but possibly with some cropping,
  27. // while maintaining the original aspect ratio of the application.
  28. NO_BORDER: 1,
  29. // The entire application is visible in the specified area without distortion while maintaining the original
  30. // aspect ratio of the application. Borders can appear on two sides of the application.
  31. SHOW_ALL: 2,
  32. // The application takes the height of the design resolution size and modifies the width of the internal
  33. // canvas so that it fits the aspect ratio of the device
  34. // no distortion will occur however you must make sure your application works on different
  35. // aspect ratios
  36. FIXED_HEIGHT: 3,
  37. // The application takes the width of the design resolution size and modifies the height of the internal
  38. // canvas so that it fits the aspect ratio of the device
  39. // no distortion will occur however you must make sure your application works on different
  40. // aspect ratios
  41. FIXED_WIDTH: 4,
  42. UNKNOWN: 5
  43. };
  44. cc.Touches = [];
  45. cc.TouchesIntergerDict = {};
  46. /**
  47. * @class
  48. * @extends cc.Class
  49. */
  50. cc.EGLView = cc.Class.extend(/** @lends cc.EGLView# */{
  51. _delegate: null,
  52. // Size of parent node that contains cc.container and cc.canvas
  53. _frameSize: null,
  54. // resolution size, it is the size appropriate for the app resources.
  55. _designResolutionSize: null,
  56. _originalDesignResolutionSize: null,
  57. // Viewport is the container's rect related to content's coordinates in pixel
  58. _viewPortRect: null,
  59. // The visible rect in content's coordinate in point
  60. _visibleRect: null,
  61. // The device's pixel ratio (for retina displays)
  62. _devicePixelRatio: 1,
  63. // the view name
  64. _viewName: "",
  65. // Custom callback for resize event
  66. _resizeCallback: null,
  67. _scaleX: 1,
  68. _originalScaleX: 1,
  69. _scaleY: 1,
  70. _originalScaleY: 1,
  71. _indexBitsUsed: 0,
  72. _maxTouches: 5,
  73. _resolutionPolicy: null,
  74. _rpExactFit: null,
  75. _rpShowAll: null,
  76. _rpNoBorder: null,
  77. _rpFixedHeight: null,
  78. _rpFixedWidth: null,
  79. _initialized: false,
  80. _captured: false,
  81. _wnd: null,
  82. _hDC: null,
  83. _hRC: null,
  84. _accelerometerKeyHook: null,
  85. _supportTouch: false,
  86. _contentTranslateLeftTop: null,
  87. _menu: null,
  88. // Parent node that contains cc.container and cc.canvas
  89. _frame: null,
  90. _frameZoomFactor: 1.0,
  91. __resizeWithBrowserSize: false,
  92. _isAdjustViewPort: true,
  93. ctor: function () {
  94. this._frame = (cc.container.parentNode === document.body) ? document.documentElement : cc.container.parentNode;
  95. this._frameSize = cc.size(0, 0);
  96. this._initFrameSize();
  97. var w = cc.canvas.width, h = cc.canvas.height;
  98. this._designResolutionSize = cc.size(w, h);
  99. this._originalDesignResolutionSize = cc.size(w, h);
  100. this._viewPortRect = cc.rect(0, 0, w, h);
  101. this._visibleRect = cc.rect(0, 0, w, h);
  102. this._delegate = cc.Director.getInstance().getTouchDispatcher();
  103. this._contentTranslateLeftTop = {left: 0, top: 0};
  104. this._viewName = "Cocos2dHTML5";
  105. cc.VisibleRect.init(this._designResolutionSize);
  106. // Setup system default resolution policies
  107. this._rpExactFit = new cc.ResolutionPolicy(cc.ContainerStrategy.EQUAL_TO_FRAME, cc.ContentStrategy.EXACT_FIT);
  108. this._rpShowAll = new cc.ResolutionPolicy(cc.ContainerStrategy.PROPORTION_TO_FRAME, cc.ContentStrategy.SHOW_ALL);
  109. this._rpNoBorder = new cc.ResolutionPolicy(cc.ContainerStrategy.EQUAL_TO_FRAME, cc.ContentStrategy.NO_BORDER);
  110. this._rpFixedHeight = new cc.ResolutionPolicy(cc.ContainerStrategy.EQUAL_TO_FRAME, cc.ContentStrategy.FIXED_HEIGHT);
  111. this._rpFixedWidth = new cc.ResolutionPolicy(cc.ContainerStrategy.EQUAL_TO_FRAME, cc.ContentStrategy.FIXED_WIDTH);
  112. this._hDC = cc.canvas;
  113. this._hRC = cc.renderContext;
  114. },
  115. // Resize helper functions
  116. _resizeEvent: function () {
  117. var width = this._originalDesignResolutionSize.width;
  118. var height = this._originalDesignResolutionSize.height;
  119. if (this._resizeCallback) {
  120. this._initFrameSize();
  121. this._resizeCallback.call();
  122. }
  123. if (width > 0)
  124. this.setDesignResolutionSize(width, height, this._resolutionPolicy);
  125. },
  126. resizeWithBrowserSize: function (enabled) {
  127. var adjustSize;
  128. if (enabled) {
  129. //enable
  130. if (!this.__resizeWithBrowserSize) {
  131. this.__resizeWithBrowserSize = true;
  132. adjustSize = this._resizeEvent.bind(this);
  133. window.addEventListener('resize', adjustSize, false);
  134. }
  135. } else {
  136. //disable
  137. if (this.__resizeWithBrowserSize) {
  138. this.__resizeWithBrowserSize = true;
  139. adjustSize = this._resizeEvent.bind(this);
  140. window.removeEventListener('resize', adjustSize, false);
  141. }
  142. }
  143. },
  144. setResizeCallback: function (callback) {
  145. if (typeof callback == "function" || callback == null) {
  146. this._resizeCallback = callback;
  147. }
  148. },
  149. _initFrameSize: function () {
  150. var locFrameSize = this._frameSize;
  151. locFrameSize.width = this._frame.clientWidth;
  152. locFrameSize.height = this._frame.clientHeight;
  153. },
  154. // hack
  155. _adjustSizeKeepCanvasSize: function (width, height) {
  156. var designWidth = this._originalDesignResolutionSize.width;
  157. var designHeight = this._originalDesignResolutionSize.height;
  158. if (designWidth > 0)
  159. this.setDesignResolutionSize(designWidth, designHeight, this._resolutionPolicy);
  160. },
  161. _setViewPortMeta: function (width, height) {
  162. if (this._isAdjustViewPort) {
  163. var viewportMetas = {"user-scalable": "no", "maximum-scale": "1.0", "initial-scale": "1.0"}, elems = document.getElementsByName("viewport"), vp, content;
  164. if (elems.length == 0) {
  165. vp = document.createElement("meta");
  166. vp.name = "viewport";
  167. vp.content = "";
  168. document.head.appendChild(vp);
  169. }
  170. else vp = elems[0];
  171. // For avoiding Android Firefox issue, to remove once firefox fixes its issue.
  172. if (cc.Browser.isMobile && cc.Browser.type == "firefox") {
  173. vp.content = "initial-scale:1";
  174. return;
  175. }
  176. content = vp.content;
  177. for (var key in viewportMetas) {
  178. var pattern = new RegExp(key);
  179. if (!pattern.test(content)) {
  180. content += (content == "" ? "" : ",") + key + "=" + viewportMetas[key];
  181. }
  182. }
  183. /*
  184. if(width<=320){
  185. width = 321;
  186. }
  187. if(height)
  188. content ="height="+height+","+content;
  189. if(width)
  190. content ="width="+width+","+content;
  191. */
  192. vp.content = content;
  193. }
  194. },
  195. // RenderTexture hacker
  196. _setScaleXYForRenderTexture: function () {
  197. //hack for RenderTexture on canvas mode when adapting multiple resolution resources
  198. var scaleFactor = cc.CONTENT_SCALE_FACTOR();
  199. this._scaleX = scaleFactor;
  200. this._scaleY = scaleFactor;
  201. },
  202. // Other helper functions
  203. _resetScale: function () {
  204. this._scaleX = this._originalScaleX;
  205. this._scaleY = this._originalScaleY;
  206. },
  207. _getUnUsedIndex: function () {
  208. var i;
  209. var temp = this._indexBitsUsed;
  210. for (i = 0; i < this._maxTouches; i++) {
  211. if (!(temp & 0x00000001)) {
  212. this._indexBitsUsed |= (1 << i);
  213. return i;
  214. }
  215. temp >>= 1;
  216. }
  217. // all bits are used
  218. return -1;
  219. },
  220. _removeUsedIndexBit: function (index) {
  221. if (index < 0 || index >= this._maxTouches) {
  222. return;
  223. }
  224. var temp = 1 << index;
  225. temp = ~temp;
  226. this._indexBitsUsed &= temp;
  227. },
  228. // Useless, just make sure the compatibility temporarily, should be removed
  229. _adjustSizeToBrowser: function () {
  230. },
  231. /**
  232. * init
  233. */
  234. initialize: function () {
  235. this._initialized = true;
  236. },
  237. adjustViewPort: function (enabled) {
  238. this._isAdjustViewPort = enabled;
  239. },
  240. /**
  241. * Force destroying EGL view, subclass must implement this method.
  242. */
  243. end: function () {
  244. },
  245. /**
  246. * Get whether render system is ready(no matter opengl or canvas),
  247. * this name is for the compatibility with cocos2d-x, subclass must implement this method.
  248. * @return {Boolean}
  249. */
  250. isOpenGLReady: function () {
  251. return (this._hDC != null && this._hRC != null);
  252. },
  253. /*
  254. * Set zoom factor for frame. This method is for debugging big resolution (e.g.new ipad) app on desktop.
  255. * @param {Number} zoomFactor
  256. */
  257. setFrameZoomFactor: function (zoomFactor) {
  258. this._frameZoomFactor = zoomFactor;
  259. this.centerWindow();
  260. cc.Director.getInstance().setProjection(cc.Director.getInstance().getProjection());
  261. },
  262. /**
  263. * Exchanges the front and back buffers, subclass must implement this method.
  264. */
  265. swapBuffers: function () {
  266. },
  267. /**
  268. * Open or close IME keyboard , subclass must implement this method.
  269. */
  270. setIMEKeyboardState: function (isOpen) {
  271. if (isOpen) {
  272. // [EAGLView sharedEGLView] becomeFirstResponder
  273. } else {
  274. // [EAGLView sharedEGLView] resignFirstResponder
  275. }
  276. },
  277. /**
  278. * <p>
  279. * The resolution translate on EGLView
  280. * </p>
  281. * @param {Number} offsetLeft
  282. * @param {Number} offsetTop
  283. */
  284. setContentTranslateLeftTop: function (offsetLeft, offsetTop) {
  285. this._contentTranslateLeftTop = {left: offsetLeft, top: offsetTop};
  286. },
  287. /**
  288. * <p>
  289. * get the resolution translate on EGLView
  290. * </p>
  291. * @return {cc.Size|Object}
  292. */
  293. getContentTranslateLeftTop: function () {
  294. return this._contentTranslateLeftTop;
  295. },
  296. /**
  297. * Get the frame size of EGL view.
  298. * In general, it returns the screen size since the EGL view is a fullscreen view.
  299. * @return {cc.Size}
  300. */
  301. getFrameSize: function () {
  302. return cc.size(this._frameSize.width, this._frameSize.height);
  303. },
  304. /**
  305. * Set the frame size of EGL view.
  306. * @param {Number} width
  307. * @param {Number} height
  308. */
  309. setFrameSize: function (width, height) {
  310. this._frameSize.width = width;
  311. this._frameSize.height = height;
  312. this._frame.style.width = width + "px";
  313. this._frame.style.height = height + "px";
  314. //this.centerWindow();
  315. this._resizeEvent();
  316. cc.Director.getInstance().setProjection(cc.Director.getInstance().getProjection());
  317. },
  318. centerWindow: function () {
  319. },
  320. setAccelerometerKeyHook: function (accelerometerKeyHook) {
  321. this._accelerometerKeyHook = accelerometerKeyHook;
  322. },
  323. /**
  324. * Get the visible area size of opengl viewport.
  325. * @return {cc.Size}
  326. */
  327. getVisibleSize: function () {
  328. return this._visibleRect._size;
  329. },
  330. /**
  331. * Get the visible origin povar of opengl viewport.
  332. * @return {cc.Point}
  333. */
  334. getVisibleOrigin: function () {
  335. return this._visibleRect._origin;
  336. },
  337. canSetContentScaleFactor: function () {
  338. return true;
  339. },
  340. /**
  341. * Get the current resolution policy
  342. * @return {cc.ResolutionPolicy}
  343. */
  344. getResolutionPolicy: function () {
  345. return this._resolutionPolicy;
  346. },
  347. /**
  348. * Set the current resolution policy
  349. * @param {cc.ResolutionPolicy|Number} resolutionPolicy
  350. */
  351. setResolutionPolicy: function (resolutionPolicy) {
  352. if (resolutionPolicy instanceof cc.ResolutionPolicy) {
  353. this._resolutionPolicy = resolutionPolicy;
  354. }
  355. // Ensure compatibility with JSB
  356. else {
  357. switch (resolutionPolicy) {
  358. case cc.RESOLUTION_POLICY.EXACT_FIT:
  359. this._resolutionPolicy = this._rpExactFit;
  360. break;
  361. case cc.RESOLUTION_POLICY.SHOW_ALL:
  362. this._resolutionPolicy = this._rpShowAll;
  363. break;
  364. case cc.RESOLUTION_POLICY.NO_BORDER:
  365. this._resolutionPolicy = this._rpNoBorder;
  366. break;
  367. case cc.RESOLUTION_POLICY.FIXED_HEIGHT:
  368. this._resolutionPolicy = this._rpFixedHeight;
  369. break;
  370. case cc.RESOLUTION_POLICY.FIXED_WIDTH:
  371. this._resolutionPolicy = this._rpFixedWidth;
  372. break;
  373. }
  374. }
  375. },
  376. /**
  377. * Set the design resolution size.
  378. * @param {Number} width Design resolution width.
  379. * @param {Number} height Design resolution height.
  380. * @param {cc.ResolutionPolicy|Number} resolutionPolicy The resolution policy desired, you may choose:
  381. * [1] ResolutionExactFit Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio, your game view will be stretched.
  382. * [2] ResolutionNoBorder Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two areas of your game view will be cut.
  383. * [3] ResolutionShowAll Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two black borders will be shown.
  384. * [4] ResolutionFixedHeight Scale the content's height to screen's height and proportionally scale its width
  385. * [5] ResolutionFixedWidth Scale the content's width to screen's width and proportionally scale its height
  386. * [cc.ResolutionPolicy] Custom resolution policy, constructed by cc.ResolutionPolicy
  387. */
  388. setDesignResolutionSize: function (width, height, resolutionPolicy) {
  389. // Defensive code
  390. if (isNaN(width) || width == 0 || isNaN(height) || height == 0) {
  391. cc.log("Resolution not valid");
  392. return;
  393. }
  394. this.setResolutionPolicy(resolutionPolicy);
  395. var policy = this._resolutionPolicy;
  396. if (policy)
  397. policy.preApply(this);
  398. else {
  399. cc.log("should set resolutionPolicy");
  400. return;
  401. }
  402. // Reinit frame size
  403. var frameW = this._frameSize.width, frameH = this._frameSize.height;
  404. if (cc.Browser.isMobile)
  405. this._setViewPortMeta(this._frameSize.width, this._frameSize.height);
  406. this._initFrameSize();
  407. // No change
  408. if (resolutionPolicy == this._resolutionPolicy
  409. && width == this._originalDesignResolutionSize.width && height == this._originalDesignResolutionSize.height
  410. && frameW == this._frameSize.width && frameH == this._frameSize.height)
  411. return;
  412. this._designResolutionSize = cc.size(width, height);
  413. this._originalDesignResolutionSize = cc.size(width, height);
  414. var result = policy.apply(this, this._designResolutionSize);
  415. if (result.scale && result.scale.length == 2) {
  416. this._scaleX = result.scale[0];
  417. this._scaleY = result.scale[1];
  418. }
  419. if (result.viewport instanceof cc.Rect) {
  420. var vp = this._viewPortRect = result.viewport, visible = this._visibleRect;
  421. visible._size.width = cc.canvas.width / this._scaleX;
  422. visible._size.height = cc.canvas.height / this._scaleY;
  423. visible._origin.x = -vp.x / this._scaleX;
  424. visible._origin.y = -vp.y / this._scaleY;
  425. }
  426. // reset director's member variables to fit visible rect
  427. var director = cc.Director.getInstance();
  428. director._winSizeInPoints = this.getDesignResolutionSize();
  429. policy.postApply(this);
  430. if (cc.renderContextType == cc.WEBGL) {
  431. // reset director's member variables to fit visible rect
  432. director._createStatsLabel();
  433. director.setGLDefaultValues();
  434. }
  435. this._originalScaleX = this._scaleX;
  436. this._originalScaleY = this._scaleY;
  437. // For editbox
  438. if (cc.DOM) {
  439. cc.DOM._resetEGLViewDiv();
  440. }
  441. cc.VisibleRect.init(this.getVisibleSize());
  442. },
  443. /**
  444. * Get design resolution size.
  445. * Default resolution size is the same as 'getFrameSize'.
  446. * @return {cc.Size}
  447. */
  448. getDesignResolutionSize: function () {
  449. return cc.size(this._designResolutionSize.width, this._designResolutionSize.height);
  450. },
  451. /**
  452. * set touch delegate
  453. * @param {cc.TouchDispatcher} delegate
  454. */
  455. setTouchDelegate: function (delegate) {
  456. this._delegate = delegate;
  457. },
  458. /**
  459. * Set opengl view port rectangle with points.
  460. * @param {Number} x
  461. * @param {Number} y
  462. * @param {Number} w width
  463. * @param {Number} h height
  464. */
  465. setViewPortInPoints: function (x, y, w, h) {
  466. var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
  467. cc.renderContext.viewport((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
  468. (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
  469. (w * locScaleX * locFrameZoomFactor),
  470. (h * locScaleY * locFrameZoomFactor));
  471. },
  472. /**
  473. * Set Scissor rectangle with points.
  474. * @param {Number} x
  475. * @param {Number} y
  476. * @param {Number} w
  477. * @param {Number} h
  478. */
  479. setScissorInPoints: function (x, y, w, h) {
  480. var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
  481. cc.renderContext.scissor((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
  482. (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
  483. (w * locScaleX * locFrameZoomFactor),
  484. (h * locScaleY * locFrameZoomFactor));
  485. },
  486. /**
  487. * Get whether GL_SCISSOR_TEST is enable
  488. */
  489. isScissorEnabled: function () {
  490. var gl = cc.renderContext;
  491. return gl.isEnabled(gl.SCISSOR_TEST);
  492. },
  493. /**
  494. * Get the current scissor rectangle
  495. * @return {cc.Rect}
  496. */
  497. getScissorRect: function () {
  498. var gl = cc.renderContext, scaleX = this._scaleX, scaleY = this._scaleY;
  499. var boxArr = gl.getParameter(gl.SCISSOR_BOX);
  500. return cc.rect((boxArr[0] - this._viewPortRect.x) / scaleX, (boxArr[1] - this._viewPortRect.y) / scaleY,
  501. boxArr[2] / scaleX, boxArr[3] / scaleY);
  502. },
  503. /**
  504. * @param {String} viewName
  505. */
  506. setViewName: function (viewName) {
  507. if (viewName != null && viewName.length > 0) {
  508. this._viewName = viewName;
  509. }
  510. },
  511. /**
  512. * get view name
  513. * @return {String}
  514. */
  515. getViewName: function () {
  516. return this._viewName;
  517. },
  518. /**
  519. * Get the opengl view port rectangle.
  520. */
  521. getViewPortRect: function () {
  522. return this._viewPortRect;
  523. },
  524. /**
  525. * Get scale factor of the horizontal direction.
  526. */
  527. getScaleX: function () {
  528. return this._scaleX;
  529. },
  530. /**
  531. * Get scale factor of the vertical direction.
  532. */
  533. getScaleY: function () {
  534. return this._scaleY;
  535. },
  536. /**
  537. * Get device pixel ratio for retina display.
  538. */
  539. getDevicePixelRatio: function() {
  540. return this._devicePixelRatio;
  541. },
  542. /**
  543. * Get the real location in view
  544. */
  545. convertToLocationInView: function (tx, ty, relatedPos) {
  546. return {x: this._devicePixelRatio * (tx - relatedPos.left), y: this._devicePixelRatio * (relatedPos.top + relatedPos.height - ty)};
  547. },
  548. /**
  549. * Touch events are handled by default; if you want to customize your handlers, please override these functions:
  550. * @param {Number} num
  551. * @param {Array} ids
  552. * @param {Array} xs
  553. * @param {Array} ys
  554. */
  555. handleTouchesBegin: function (num, ids, xs, ys) {
  556. var arr = [], locViewPortRect = this._viewPortRect, locScaleX = this._scaleX, locScaleY = this._scaleY;
  557. for (var i = 0; i < num; ++i) {
  558. var id = ids[i];
  559. var x = xs[i];
  560. var y = ys[i];
  561. var index = cc.TouchesIntergerDict[id];
  562. var unusedIndex = 0;
  563. // it is a new touch
  564. if (index == null) {
  565. unusedIndex = this._getUnUsedIndex();
  566. // The touches is more than MAX_TOUCHES ?
  567. if (unusedIndex == -1) {
  568. cc.log("The touches is more than MAX_TOUCHES, nUnusedIndex = " + unusedIndex);
  569. continue;
  570. }
  571. var touch = cc.Touches[unusedIndex] = new cc.Touch();
  572. touch.setTouchInfo(unusedIndex, (x - locViewPortRect.x) / locScaleX,
  573. (y - locViewPortRect.y) / locScaleY);
  574. cc.TouchesIntergerDict[id] = 0 | unusedIndex;
  575. arr.push(touch);
  576. }
  577. }
  578. if (arr.length !== 0)
  579. this._delegate.touchesBegan(arr, null);
  580. },
  581. /**
  582. * @param {Number} num
  583. * @param {Number} ids
  584. * @param {Number} xs
  585. * @param {Number} ys
  586. */
  587. handleTouchesMove: function (num, ids, xs, ys) {
  588. var arr = [];
  589. var locScaleX = this._scaleX, locScaleY = this._scaleY, locViewPortX = this._viewPortRect.x, locViewPortY = this._viewPortRect.y;
  590. for (var i = 0; i < num; ++i) {
  591. var id = ids[i];
  592. var x = xs[i];
  593. var y = ys[i];
  594. var index = cc.TouchesIntergerDict[id];
  595. if (index == null) {
  596. //cc.log("if the index doesn't exist, it is an error");
  597. continue;
  598. }
  599. var touch = cc.Touches[index];
  600. if (touch) {
  601. touch.setTouchInfo(index, (x - locViewPortX) / locScaleX,
  602. (y - locViewPortY) / locScaleY);
  603. arr.push(touch);
  604. }
  605. else {
  606. // It is error, should return.
  607. //cc.log("Moving touches with id: " + id + " error");
  608. return;
  609. }
  610. }
  611. if (arr.length == 0) {
  612. //cc.log("touchesMoved: count = 0");
  613. return;
  614. }
  615. this._delegate.touchesMoved(arr, null);
  616. },
  617. /**
  618. * @param {Number} num
  619. * @param {Number} ids
  620. * @param {Number} xs
  621. * @param {Number} ys
  622. */
  623. handleTouchesEnd: function (num, ids, xs, ys) {
  624. var arr = [];
  625. this.getSetOfTouchesEndOrCancel(arr, num, ids, xs, ys);
  626. this._delegate.touchesEnded(arr, null);
  627. },
  628. /**
  629. * @param {Number} num
  630. * @param {Number} ids
  631. * @param {Number} xs
  632. * @param {Number} ys
  633. */
  634. handleTouchesCancel: function (num, ids, xs, ys) {
  635. var arr = [];
  636. this.getSetOfTouchesEndOrCancel(arr, num, ids, xs, ys);
  637. this._delegate.touchesCancelled(arr, null);
  638. },
  639. /**
  640. * @param {Array} arr
  641. * @param {Number} num
  642. * @param {Number} ids
  643. * @param {Number} xs
  644. * @param {Number} ys
  645. */
  646. getSetOfTouchesEndOrCancel: function (arr, num, ids, xs, ys) {
  647. var locScaleX = this._scaleX, locScaleY = this._scaleY, locViewPortRect = this._viewPortRect;
  648. for (var i = 0; i < num; ++i) {
  649. var id = ids[i];
  650. var x = xs[i];
  651. var y = ys[i];
  652. var index = cc.TouchesIntergerDict[id];
  653. if (index == null) {
  654. //cc.log("if the index doesn't exist, it is an error");
  655. continue;
  656. }
  657. /* Add to the set to send to the director */
  658. var touch = cc.Touches[index];
  659. if (touch) {
  660. //cc.log("Ending touches with id: " + id + ", x=" + x + ", y=" + y);
  661. touch.setTouchInfo(index, (x - locViewPortRect.x) / locScaleX,
  662. (y - locViewPortRect.y) / locScaleY);
  663. arr.push(touch);
  664. // release the object
  665. cc.Touches[index] = null;
  666. this._removeUsedIndexBit(index);
  667. delete cc.TouchesIntergerDict[id];
  668. } else {
  669. //cc.log("Ending touches with id: " + id + " error");
  670. return;
  671. }
  672. }
  673. },
  674. // Pass the touches to the superview
  675. touchesBegan: function (touches, event) {
  676. var ids = [];
  677. var xs = [];
  678. var ys = [];
  679. var i = 0;
  680. var touch;
  681. for (var j = 0; j < touches.length; j++) {
  682. touch = touches[j];
  683. ids[i] = touch.getId() || j;
  684. xs[i] = touch.getLocation().x;
  685. ys[i] = touch.getLocation().y;
  686. ++i;
  687. }
  688. this.handleTouchesBegin(i, ids, xs, ys);
  689. },
  690. touchesMoved: function (touches, event) {
  691. var ids = [];
  692. var xs = [];
  693. var ys = [];
  694. var i = 0;
  695. var touch;
  696. for (var j = 0; j < touches.length; j++) {
  697. touch = touches[j];
  698. ids[i] = touch.getId() || j;
  699. xs[i] = touch.getLocation().x;
  700. ys[i] = touch.getLocation().y;
  701. ++i;
  702. }
  703. this.handleTouchesMove(i, ids, xs, ys);
  704. },
  705. touchesEnded: function (touches, event) {
  706. var ids = [];
  707. var xs = [];
  708. var ys = [];
  709. var i = 0;
  710. var touch;
  711. for (var j = 0; j < touches.length; j++) {
  712. touch = touches[j];
  713. ids[i] = touch.getId() || j;
  714. xs[i] = touch.getLocation().x;
  715. ys[i] = touch.getLocation().y;
  716. ++i;
  717. }
  718. this.handleTouchesEnd(i, ids, xs, ys);
  719. },
  720. touchesCancelled: function (touches, event) {
  721. var ids = [];
  722. var xs = [];
  723. var ys = [];
  724. var i = 0;
  725. var touch;
  726. for (var j = 0; j < touches.length; j++) {
  727. touch = touches[j];
  728. ids[i] = touch.getId() || j;
  729. xs[i] = touch.getLocation().x;
  730. ys[i] = touch.getLocation().y;
  731. ++i;
  732. }
  733. this.handleTouchesCancel(i, ids, xs, ys);
  734. }
  735. });
  736. cc.EGLView.getInstance = function () {
  737. if (!this._instance) {
  738. // First init director
  739. cc.Director.getInstance();
  740. this._instance = this._instance || new cc.EGLView();
  741. this._instance.initialize();
  742. }
  743. return this._instance;
  744. };
  745. /**
  746. * <p>cc.ContainerStrategy class is the root strategy class of container's scale strategy,
  747. * it controls the behavior of how to scale the cc.container and cc.canvas object</p>
  748. *
  749. * @class
  750. * @extends cc.Class
  751. */
  752. cc.ContainerStrategy = cc.Class.extend({
  753. // Adjust canvas's size for retina display
  754. _adjustRetina: false,
  755. /**
  756. * Manipulation before appling the strategy
  757. * @param {cc.EGLView} The target view
  758. */
  759. preApply: function (view) {
  760. if(sys.os == "iOS" || sys.os == "OS X")
  761. this._adjustRetina = true;
  762. },
  763. /**
  764. * Function to apply this strategy
  765. * @param {cc.EGLView} view
  766. * @param {cc.Size} designedResolution
  767. */
  768. apply: function (view, designedResolution) {
  769. },
  770. /**
  771. * Manipulation after appling the strategy
  772. * @param {cc.EGLView} The target view
  773. */
  774. postApply: function (view) {
  775. },
  776. _setupContainer: function (view, w, h) {
  777. var frame = view._frame;
  778. if (cc.Browser.isMobile && frame == document.documentElement) {
  779. // Automatically full screen when user touches on mobile version
  780. cc.Screen.getInstance().autoFullScreen(frame);
  781. }
  782. var locCanvasElement = cc.canvas, locContainer = cc.container;
  783. // Setup container
  784. locContainer.style.width = locCanvasElement.style.width = w + "px";
  785. locContainer.style.height = locCanvasElement.style.height = h + "px";
  786. // Setup pixel ratio for retina display
  787. var devicePixelRatio = view._devicePixelRatio = 1;
  788. if (this._adjustRetina)
  789. devicePixelRatio = view._devicePixelRatio = window.devicePixelRatio || 1;
  790. // Setup canvas
  791. locCanvasElement.width = w * devicePixelRatio;
  792. locCanvasElement.height = h * devicePixelRatio;
  793. var body = document.body, style;
  794. if (body && (style = body.style)) {
  795. style.paddingTop = style.paddingTop || "0px";
  796. style.paddingRight = style.paddingRight || "0px";
  797. style.paddingBottom = style.paddingBottom || "0px";
  798. style.paddingLeft = style.paddingLeft || "0px";
  799. style.borderTop = style.borderTop || "0px";
  800. style.borderRight = style.borderRight || "0px";
  801. style.borderBottom = style.borderBottom || "0px";
  802. style.borderLeft = style.borderLeft || "0px";
  803. style.marginTop = style.marginTop || "0px";
  804. style.marginRight = style.marginRight || "0px";
  805. style.marginBottom = style.marginBottom || "0px";
  806. style.marginLeft = style.marginLeft || "0px";
  807. }
  808. },
  809. _fixContainer: function () {
  810. // Add container to document body
  811. document.body.insertBefore(cc.container, document.body.firstChild);
  812. // Set body's width height to window's size, and forbid overflow, so that game will be centered
  813. var bs = document.body.style;
  814. bs.width = window.innerWidth + "px";
  815. bs.height = window.innerHeight + "px";
  816. bs.overflow = "hidden";
  817. // Body size solution doesn't work on all mobile browser so this is the aleternative: fixed container
  818. var contStyle = cc.container.style;
  819. contStyle.position = "fixed";
  820. contStyle.left = contStyle.top = "0px";
  821. // Reposition body
  822. document.body.scrollTop = 0;
  823. }
  824. });
  825. /**
  826. * <p>cc.ContentStrategy class is the root strategy class of content's scale strategy,
  827. * it controls the behavior of how to scale the scene and setup the viewport for the game</p>
  828. *
  829. * @class
  830. * @extends cc.Class
  831. */
  832. cc.ContentStrategy = cc.Class.extend({
  833. _result: {
  834. scale: [1, 1],
  835. viewport: null
  836. },
  837. _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) {
  838. // Makes content fit better the canvas
  839. Math.abs(containerW - contentW) < 2 && (contentW = containerW);
  840. Math.abs(containerH - contentH) < 2 && (contentH = containerH);
  841. var viewport = cc.rect(Math.round((containerW - contentW) / 2),
  842. Math.round((containerH - contentH) / 2),
  843. contentW, contentH);
  844. // Translate the content
  845. if (cc.renderContextType == cc.CANVAS)
  846. cc.renderContext.translate(viewport.x, viewport.y + contentH);
  847. this._result.scale = [scaleX, scaleY];
  848. this._result.viewport = viewport;
  849. return this._result;
  850. },
  851. /**
  852. * Manipulation before appling the strategy
  853. * @param {cc.EGLView} The target view
  854. */
  855. preApply: function (view) {
  856. },
  857. /**
  858. * Function to apply this strategy
  859. * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
  860. * The target view can then apply these value to itself, it's prefered not to modify directly its private variables
  861. * @param {cc.EGLView} view
  862. * @param {cc.Size} designedResolution
  863. * @return {object} scaleAndViewportRect
  864. */
  865. apply: function (view, designedResolution) {
  866. return {"scale": [1, 1]};
  867. },
  868. /**
  869. * Manipulation after appling the strategy
  870. * @param {cc.EGLView} The target view
  871. */
  872. postApply: function (view) {
  873. }
  874. });
  875. (function () {
  876. // Container scale strategys
  877. var EqualToFrame = cc.ContainerStrategy.extend({
  878. apply: function (view) {
  879. this._setupContainer(view, view._frameSize.width, view._frameSize.height);
  880. }
  881. });
  882. var ProportionalToFrame = cc.ContainerStrategy.extend({
  883. apply: function (view, designedResolution) {
  884. var frameW = view._frameSize.width, frameH = view._frameSize.height, containerStyle = cc.container.style,
  885. designW = designedResolution.width, designH = designedResolution.height,
  886. scaleX = frameW / designW, scaleY = frameH / designH,
  887. containerW, containerH;
  888. scaleX < scaleY ? (containerW = frameW, containerH = designH * scaleX) : (containerW = designW * scaleY, containerH = frameH);
  889. // Adjust container size with integer value
  890. var offx = Math.round((frameW - containerW) / 2);
  891. var offy = Math.round((frameH - containerH) / 2);
  892. containerW = frameW - 2 * offx;
  893. containerH = frameH - 2 * offy;
  894. this._setupContainer(view, containerW, containerH);
  895. // Setup container's margin
  896. containerStyle.marginLeft = offx + "px";
  897. containerStyle.marginRight = offx + "px";
  898. containerStyle.marginTop = offy + "px";
  899. containerStyle.marginBottom = offy + "px";
  900. }
  901. });
  902. var EqualToWindow = EqualToFrame.extend({
  903. preApply: function (view) {
  904. this._super(view);
  905. view._frame = document.documentElement;
  906. },
  907. apply: function (view) {
  908. this._super(view);
  909. this._fixContainer();
  910. }
  911. });
  912. var ProportionalToWindow = ProportionalToFrame.extend({
  913. preApply: function (view) {
  914. this._super(view);
  915. view._frame = document.documentElement;
  916. },
  917. apply: function (view, designedResolution) {
  918. this._super(view, designedResolution);
  919. this._fixContainer();
  920. }
  921. });
  922. var OriginalContainer = cc.ContainerStrategy.extend({
  923. apply: function (view) {
  924. this._setupContainer(view, cc.canvas.width, cc.canvas.height);
  925. }
  926. });
  927. // #NOT STABLE on Android# Alias: Strategy that makes the container's size equals to the window's size
  928. // cc.ContainerStrategy.EQUAL_TO_WINDOW = new EqualToWindow();
  929. // #NOT STABLE on Android# Alias: Strategy that scale proportionally the container's size to window's size
  930. // cc.ContainerStrategy.PROPORTION_TO_WINDOW = new ProportionalToWindow();
  931. // Alias: Strategy that makes the container's size equals to the frame's size
  932. cc.ContainerStrategy.EQUAL_TO_FRAME = new EqualToFrame();
  933. // Alias: Strategy that scale proportionally the container's size to frame's size
  934. cc.ContainerStrategy.PROPORTION_TO_FRAME = new ProportionalToFrame();
  935. // Alias: Strategy that keeps the original container's size
  936. cc.ContainerStrategy.ORIGINAL_CONTAINER = new OriginalContainer();
  937. // Content scale strategys
  938. var ExactFit = cc.ContentStrategy.extend({
  939. apply: function (view, designedResolution) {
  940. var containerW = cc.canvas.width, containerH = cc.canvas.height,
  941. scaleX = containerW / designedResolution.width, scaleY = containerH / designedResolution.height;
  942. return this._buildResult(containerW, containerH, containerW, containerH, scaleX, scaleY);
  943. }
  944. });
  945. var ShowAll = cc.ContentStrategy.extend({
  946. apply: function (view, designedResolution) {
  947. var containerW = cc.canvas.width, containerH = cc.canvas.height,
  948. designW = designedResolution.width, designH = designedResolution.height,
  949. scaleX = containerW / designW, scaleY = containerH / designH, scale = 0,
  950. contentW, contentH;
  951. scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale)
  952. : (scale = scaleY, contentW = designW * scale, contentH = containerH);
  953. return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
  954. }
  955. });
  956. var NoBorder = cc.ContentStrategy.extend({
  957. apply: function (view, designedResolution) {
  958. var containerW = cc.canvas.width, containerH = cc.canvas.height,
  959. designW = designedResolution.width, designH = designedResolution.height,
  960. scaleX = containerW / designW, scaleY = containerH / designH, scale,
  961. contentW, contentH;
  962. scaleX < scaleY ? (scale = scaleY, contentW = designW * scale, contentH = containerH)
  963. : (scale = scaleX, contentW = containerW, contentH = designH * scale);
  964. return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
  965. }
  966. });
  967. var FixedHeight = cc.ContentStrategy.extend({
  968. apply: function (view, designedResolution) {
  969. var containerW = cc.canvas.width, containerH = cc.canvas.height,
  970. designH = designedResolution.height, scale = containerH / designH,
  971. contentW = containerW, contentH = containerH;
  972. return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
  973. },
  974. postApply: function (view) {
  975. cc.Director.getInstance()._winSizeInPoints = view.getVisibleSize();
  976. }
  977. });
  978. var FixedWidth = cc.ContentStrategy.extend({
  979. apply: function (view, designedResolution) {
  980. var containerW = cc.canvas.width, containerH = cc.canvas.height,
  981. designW = designedResolution.width, scale = containerW / designW,
  982. contentW = containerW, contentH = containerH;
  983. return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
  984. },
  985. postApply: function (view) {
  986. cc.Director.getInstance()._winSizeInPoints = view.getVisibleSize();
  987. }
  988. });
  989. // Alias: Strategy to scale the content's size to container's size, non proportional
  990. cc.ContentStrategy.EXACT_FIT = new ExactFit();
  991. // Alias: Strategy to scale the content's size proportionally to maximum size and keeps the whole content area to be visible
  992. cc.ContentStrategy.SHOW_ALL = new ShowAll();
  993. // Alias: Strategy to scale the content's size proportionally to fill the whole container area
  994. cc.ContentStrategy.NO_BORDER = new NoBorder();
  995. // Alias: Strategy to scale the content's height to container's height and proportionally scale its width
  996. cc.ContentStrategy.FIXED_HEIGHT = new FixedHeight();
  997. // Alias: Strategy to scale the content's width to container's width and proportionally scale its height
  998. cc.ContentStrategy.FIXED_WIDTH = new FixedWidth();
  999. })();
  1000. /**
  1001. * <p>cc.ResolutionPolicy class is the root strategy class of scale strategy,
  1002. * its main task is to maintain the compatibility with Cocos2d-x</p>
  1003. *
  1004. * @class
  1005. * @extends cc.Class
  1006. */
  1007. cc.ResolutionPolicy = cc.Class.extend({
  1008. _containerStrategy: null,
  1009. _contentStrategy: null,
  1010. ctor: function (containerStg, contentStg) {
  1011. this.setContainerStrategy(containerStg);
  1012. this.setContentStrategy(contentStg);
  1013. },
  1014. /**
  1015. * Manipulation before appling the resolution policy
  1016. * @param {cc.EGLView} The target view
  1017. */
  1018. preApply: function (view) {
  1019. this._containerStrategy.preApply(view);
  1020. this._contentStrategy.preApply(view);
  1021. },
  1022. /**
  1023. * Function to apply this resolution policy
  1024. * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
  1025. * The target view can then apply these value to itself, it's prefered not to modify directly its private variables
  1026. * @param {cc.EGLView} The target view
  1027. * @param {cc.Size} The user defined design resolution
  1028. * @return {object} An object contains the scale X/Y values and the viewport rect
  1029. */
  1030. apply: function (view, designedResolution) {
  1031. this._containerStrategy.apply(view, designedResolution);
  1032. return this._contentStrategy.apply(view, designedResolution);
  1033. },
  1034. /**
  1035. * Manipulation after appling the strategy
  1036. * @param {cc.EGLView} The target view
  1037. */
  1038. postApply: function (view) {
  1039. this._containerStrategy.postApply(view);
  1040. this._contentStrategy.postApply(view);
  1041. },
  1042. /**
  1043. * Setup the container's scale strategy
  1044. * @param {cc.ContainerStrategy} containerStg
  1045. */
  1046. setContainerStrategy: function (containerStg) {
  1047. if (containerStg instanceof cc.ContainerStrategy)
  1048. this._containerStrategy = containerStg;
  1049. },
  1050. /**
  1051. * Setup the content's scale strategy
  1052. * @param {cc.ContentStrategy} contentStg
  1053. */
  1054. setContentStrategy: function (contentStg) {
  1055. if (contentStg instanceof cc.ContentStrategy)
  1056. this._contentStrategy = contentStg;
  1057. }
  1058. });