PageRenderTime 58ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/mad-components/MadComponentsStage3D/src/com/danielfreeman/stage3Dacceleration/PanelScaling.as

http://mad-components.googlecode.com/
ActionScript | 389 lines | 244 code | 58 blank | 87 comment | 6 complexity | 83efc9e74b7dcd3cf4493b2f4503b8f8 MD5 | raw file
  1. /**
  2. * <p>Original Author: Daniel Freeman</p>
  3. *
  4. * <p>Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:</p>
  10. *
  11. * <p>The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.</p>
  13. *
  14. * <p>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.</p>
  21. *
  22. * <p>Licensed under The MIT License</p>
  23. * <p>Redistributions of files must retain the above copyright notice.</p>
  24. */
  25. package com.danielfreeman.stage3Dacceleration {
  26. import flash.trace.Trace;
  27. import flash.events.MouseEvent;
  28. import flash.display.DisplayObject;
  29. import com.danielfreeman.madcomponents.*;
  30. import com.adobe.utils.*;
  31. import flash.display.Sprite;
  32. import flash.display.Bitmap;
  33. import flash.display3D.Context3DProgramType;
  34. import flash.display3D.Context3DVertexBufferFormat;
  35. import flash.display3D.IndexBuffer3D;
  36. import flash.display3D.Program3D;
  37. import flash.display3D.VertexBuffer3D;
  38. import flash.geom.Matrix;
  39. import flash.geom.Matrix3D;
  40. import flash.display.BitmapData;
  41. import flash.geom.Point;
  42. import flash.geom.Rectangle;
  43. import flash.display3D.textures.Texture;
  44. import flash.display3D.Context3DTextureFormat;
  45. import flash.events.Event;
  46. import flash.display.DisplayObject;
  47. public class PanelScaling extends Stage3DAcceleration {
  48. public static const SCALE_COMPLETE:String = "scaleComplete";
  49. public static const REVERSE_COMPLETE:String = "reverseComplete";
  50. protected static const QUADS:int = 2;
  51. protected static const INCREMENT:Number = 0.1;
  52. protected static const POPUP_INCREMENT:Number = 0.2;
  53. protected static const POPUP_SMALL:Number = 0.7;
  54. protected var _backgroundTextureBitMapData:BitmapData;
  55. protected var _sourcePanelTextureBitMapData:BitmapData;
  56. protected var _destinationPanelTextureBitMapData:BitmapData;
  57. protected var _indexBuffer:IndexBuffer3D;
  58. protected var _startKeyVertexBuffer:VertexBuffer3D;
  59. protected var _finishKeyVertexBuffer:VertexBuffer3D;
  60. protected var _uvtStartVertexBuffer:VertexBuffer3D;
  61. protected var _uvFinishVertexBuffer:VertexBuffer3D;
  62. protected var _panelScalingVertexShader:AGALMiniAssembler = new AGALMiniAssembler();
  63. protected var _panelScalingFragmentShader:AGALMiniAssembler = new AGALMiniAssembler();
  64. protected var _panelScalingShaderProgram:Program3D;
  65. protected var _backgroundTexture:Texture;
  66. protected var _sourcePanelTexture:Texture;
  67. protected var _destinationPanelTexture:Texture = null;
  68. protected var _backgroundRectangle:Rectangle;
  69. protected var _sourcePanelRectangle:Rectangle;
  70. protected var _destinationPanelRectangle:Rectangle;
  71. protected var _count:Number = 0.0;
  72. protected var _backgroundColour:uint = 0xFFFFFFFF;
  73. protected var _reverse:Boolean = false;
  74. protected var _window:UIWindow = null;
  75. protected var _popUp:Boolean = false;
  76. protected var _deactivate:Boolean = false;
  77. /**
  78. * This class impliments two animated transitions that may be applied to MadComponents forms.
  79. *
  80. * The first is a panel scaling effect that's often seen on Tablet UIs.
  81. * There is an animated resizing, combined with a cross-fade of the UI appearance.
  82. *
  83. * The second transition is for pop-up windows that appear to properly pop-out. A rapid scale effect.
  84. */
  85. public function PanelScaling() {
  86. initialise();
  87. }
  88. /**
  89. * The vertex shader impliments a tween between two sets of vertices, and a tween between two sets of UV values.
  90. *
  91. * The fragment shader impliments a cross-fade between two textures, or optionally dispalys a third, non-cross-faded texture.
  92. */
  93. public function initialise():void {
  94. _panelScalingVertexShader.assemble( Context3DProgramType.VERTEX,
  95. "mul vt0, va0, vc0.yyyy \n" + // t * start position
  96. "mul vt1, va1, vc0.xxxx \n" + // (1-t) * end position
  97. "add op, vt0, vt1 \n" + // add
  98. "mov v0, va2 \n" + // interpolate UVT
  99. "mul vt0, va2, vc0.yyyy \n" + // t * start position
  100. "mul vt1, va3, vc0.xxxx \n" + // (1-t) * end position
  101. "add v1, vt0, vt1 \n" // add
  102. );
  103. _panelScalingFragmentShader.assemble( Context3DProgramType.FRAGMENT,
  104. "tex ft0, v0.xy, fs0 <2d,linear,nomip> \n" + // texture 0
  105. "tex ft1, v0.xy, fs1 <2d,linear,nomip> \n" + // texture 1
  106. "tex ft2, v1.xy, fs2 <2d,linear,nomip> \n" + // texture 2
  107. "mul ft1, ft1, fc0.yyyy \n" + // t * start position
  108. "mul ft2, ft2, fc0.xxxx \n" + // (1-t) * end position
  109. "add ft1, ft1, ft2 \n" + // add
  110. "mul ft0, ft0, v0.zzzz \n" +
  111. "sub ft2.x, fc0.w, v0.z \n" + // Option to use texture0
  112. "mul ft1, ft1, ft2.xxxx \n" +
  113. "add oc, ft0, ft1 \n"
  114. );
  115. _panelScalingShaderProgram = _context3D.createProgram();
  116. _panelScalingShaderProgram.upload( _panelScalingVertexShader.agalcode, _panelScalingFragmentShader.agalcode);
  117. _startKeyVertexBuffer = _context3D.createVertexBuffer(QUADS * 4, 3);
  118. _finishKeyVertexBuffer = _context3D.createVertexBuffer(QUADS * 4, 3);
  119. _uvtStartVertexBuffer = _context3D.createVertexBuffer(QUADS * 4, 3);
  120. _uvFinishVertexBuffer = _context3D.createVertexBuffer(QUADS * 4, 2);
  121. var indices:Vector.<uint> = Vector.<uint> ([ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7]);
  122. _indexBuffer = _context3D.createIndexBuffer( indices.length );
  123. _indexBuffer.uploadFromVector(indices, 0, indices.length );
  124. }
  125. /**
  126. * Set the Stage3D background colour
  127. */
  128. public function set backgroundColour(value:uint):void {
  129. _backgroundColour = value;
  130. }
  131. /**
  132. * Apply scale to rectange width and height
  133. */
  134. protected function applyScale(rectangle:Rectangle):void {
  135. rectangle.width*=UI.scale;
  136. rectangle.height*=UI.scale;
  137. }
  138. /**
  139. * Upload background texture
  140. */
  141. public function backgroundTexture(panel:IContainerUI):void {
  142. _backgroundRectangle = new Rectangle(0, 0, _screen.stage.stageWidth, _screen.stage.stageHeight);
  143. _backgroundTextureBitMapData = new BitmapData(power2(_backgroundRectangle.width), power2(_backgroundRectangle.height), false, _backgroundColour);
  144. saveTexture(_backgroundTextureBitMapData, Sprite(panel), _backgroundRectangle);
  145. _backgroundTexture = _context3D.createTexture(_backgroundTextureBitMapData.width, _backgroundTextureBitMapData.height, Context3DTextureFormat.BGRA, false);
  146. _backgroundTexture.uploadFromBitmapData(_backgroundTextureBitMapData);
  147. }
  148. /**
  149. * Upload souce panel texture for cross-fade scale effect
  150. */
  151. public function sourcePanelBackground(panel:IContainerUI):void {
  152. var globalPoint:Point = Sprite(panel).localToGlobal(new Point(0,0));
  153. _sourcePanelRectangle = new Rectangle(globalPoint.x, globalPoint.y, panel.attributes.width + (panel.xml.@border=="true" ? 2*UI.PADDING : 0), panel.attributes.height + (panel.xml.@border=="true" ? 2*UI.PADDING : 0));
  154. applyScale(_sourcePanelRectangle);
  155. _sourcePanelTextureBitMapData = new BitmapData(power2(_sourcePanelRectangle.width), power2(_sourcePanelRectangle.height), false, _backgroundColour);
  156. saveTexture(_sourcePanelTextureBitMapData, Sprite(panel), new Rectangle(0, 0, _sourcePanelRectangle.width, _sourcePanelRectangle.height));
  157. _sourcePanelTexture = _context3D.createTexture(_sourcePanelTextureBitMapData.width, _sourcePanelTextureBitMapData.height, Context3DTextureFormat.BGRA, false);
  158. _sourcePanelTexture.uploadFromBitmapData(_sourcePanelTextureBitMapData);
  159. }
  160. /**
  161. * Upload destination panel texture for cross-fade scale effect
  162. */
  163. public function destinationPanelBackground(panel:IContainerUI):void {
  164. var globalPoint:Point = Sprite(panel).localToGlobal(new Point(0,0));
  165. _destinationPanelRectangle = new Rectangle(globalPoint.x, globalPoint.y, panel.attributes.width + (panel.xml.@border=="true" ? 2*UI.PADDING : 0), panel.attributes.height + (panel.xml.@border=="true" ? 2*UI.PADDING : 0));
  166. applyScale(_destinationPanelRectangle);
  167. _destinationPanelTextureBitMapData = new BitmapData(power2(_destinationPanelRectangle.width), power2(_destinationPanelRectangle.height), false, _backgroundColour);
  168. saveTexture(_destinationPanelTextureBitMapData, Sprite(panel), new Rectangle(0, 0, _destinationPanelRectangle.width, _destinationPanelRectangle.height));
  169. _destinationPanelTexture = _context3D.createTexture(_destinationPanelTextureBitMapData.width, _destinationPanelTextureBitMapData.height, Context3DTextureFormat.BGRA, false);
  170. _destinationPanelTexture.uploadFromBitmapData(_destinationPanelTextureBitMapData);
  171. }
  172. /**
  173. * A 2x2 quad
  174. */
  175. protected function fill():Vector.<Number> {
  176. return Vector.<Number> ([
  177. // X, Y, Z,
  178. -1.0, -1.0, 0.02,
  179. 1.0, -1.0, 0.02,
  180. 1.0, 1.0, 0.02,
  181. -1.0, 1.0, 0.02
  182. ]);
  183. }
  184. /**
  185. * A scaled quad converted to Stage3D coordinates
  186. */
  187. protected function quad(rectangle:Rectangle, multiplier:Number = 1.0):Vector.<Number> {
  188. return Vector.<Number> ([
  189. multiplier*toGraphX(rectangle.x), -multiplier*toGraphY(rectangle.y+rectangle.height), 0.01,
  190. multiplier*toGraphX(rectangle.x+rectangle.width), -multiplier*toGraphY(rectangle.y+rectangle.height), 0.01,
  191. multiplier*toGraphX(rectangle.x+rectangle.width), -multiplier*toGraphY(rectangle.y), 0.01,
  192. multiplier*toGraphX(rectangle.x), -multiplier*toGraphY(rectangle.y), 0.01
  193. ]);
  194. }
  195. /**
  196. * Generate UV values
  197. */
  198. protected function uv(rectangle:Rectangle):Vector.<Number> {
  199. var textureRight:Number = rectangle.width / power2(rectangle.width);
  200. var textureBottom:Number = rectangle.height / power2(rectangle.height);
  201. return Vector.<Number> ([
  202. 0, textureBottom,
  203. textureRight, textureBottom,
  204. textureRight, 0,
  205. 0, 0
  206. ]);
  207. }
  208. /**
  209. * Generate UV values with a flag which indicates which texture to use
  210. */
  211. protected function uvt(rectangle:Rectangle, flag:Number):Vector.<Number> {
  212. var textureRight:Number = rectangle.width / power2(rectangle.width);
  213. var textureBottom:Number = rectangle.height / power2(rectangle.height);
  214. return Vector.<Number> ([
  215. 0, textureBottom, flag,
  216. textureRight, textureBottom, flag,
  217. textureRight, 0, flag,
  218. 0, 0, flag
  219. ]);
  220. }
  221. /**
  222. * Do scale / cross-fade effect
  223. */
  224. protected function doScaleEffect(reverse:Boolean = false, popUp:Boolean = false):void {
  225. _reverse = reverse;
  226. _popUp = popUp;
  227. _deactivate = false;
  228. var startKeyVertices:Vector.<Number> = fill().concat(quad(_sourcePanelRectangle, popUp ? POPUP_SMALL : 1.0));
  229. _startKeyVertexBuffer.uploadFromVector(startKeyVertices, 0, startKeyVertices.length/3);
  230. var finishKeyVertices:Vector.<Number> = fill().concat(popUp ? quad(_sourcePanelRectangle) : quad(_destinationPanelRectangle));
  231. _finishKeyVertexBuffer.uploadFromVector(finishKeyVertices, 0, finishKeyVertices.length/3);
  232. var uvtStartVertices:Vector.<Number> = uvt(_backgroundRectangle, 1.0).concat(uvt(_sourcePanelRectangle, 0.0));
  233. _uvtStartVertexBuffer.uploadFromVector(uvtStartVertices, 0, uvtStartVertices.length/3);
  234. var uvFinishVertices:Vector.<Number> = uv(_backgroundRectangle).concat(uv(popUp ? _sourcePanelRectangle : _destinationPanelRectangle));
  235. _uvFinishVertexBuffer.uploadFromVector(uvFinishVertices, 0, uvFinishVertices.length/2);
  236. _count = _reverse ? 1.0 : 0.0;
  237. UI.uiLayer.visible = false;
  238. activate(this);
  239. onEnterFrame(this, onEnterFrameScaleTransition);
  240. }
  241. /**
  242. * Activate scale effect
  243. */
  244. public function scaleEffect():void {
  245. doScaleEffect(false);
  246. }
  247. /**
  248. * Activate inverse scale effect
  249. */
  250. public function goBack():void {
  251. doScaleEffect(true);
  252. }
  253. /**
  254. * Activate pop-up window effect
  255. */
  256. public function popUp(window:UIWindow):void {
  257. UI.showPopUp(window);
  258. _window = window;
  259. UI.uiLayer.visible = false;
  260. UI.windowLayer.visible = false;
  261. doScaleEffect(false, true);
  262. }
  263. override public function enable():void {
  264. _context3D.setVertexBufferAt( 0, _startKeyVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3 ); //va0
  265. _context3D.setVertexBufferAt( 1, _finishKeyVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3 ); //va1
  266. _context3D.setVertexBufferAt( 2, _uvtStartVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3 ); //va2
  267. _context3D.setVertexBufferAt( 3, _uvFinishVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2 ); //va3
  268. _context3D.setTextureAt(0, _backgroundTexture); //fs0
  269. _context3D.setTextureAt(1, _sourcePanelTexture); //fs1
  270. _context3D.setTextureAt(2, _popUp ? _sourcePanelTexture : _destinationPanelTexture); //fs2
  271. _context3D.setProgram(_panelScalingShaderProgram);
  272. }
  273. override public function disable():void {
  274. _context3D.setVertexBufferAt( 0, null ); //va0
  275. _context3D.setVertexBufferAt( 1, null ); //va1
  276. _context3D.setVertexBufferAt( 2, null ); //va2
  277. _context3D.setVertexBufferAt( 3, null ); //va3
  278. _context3D.setTextureAt(0, null); //fs0
  279. _context3D.setTextureAt(1, null); //fs1
  280. _context3D.setTextureAt(2, null); //fs2
  281. }
  282. /**
  283. * Render effect
  284. */
  285. protected function onEnterFrameScaleTransition(event:Event = null):void {
  286. _context3D.clear((_backgroundColour>>32 & 0xff)/0xff, (_backgroundColour>>16 & 0xff)/0xff, (_backgroundColour & 0xff)/0xff);
  287. var easedCount:Number = easing(_count);
  288. _context3D.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 0, Vector.<Number>([ easedCount, (1.0 - easedCount), 0.0, 1.0 ]) ); //vc0
  289. _context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([ easedCount, (1.0 - easedCount), 0.0, 1.0 ]) ); //fc0
  290. _context3D.drawTriangles(_indexBuffer);
  291. _context3D.present();
  292. _count += _window ? POPUP_INCREMENT : (_reverse ? -INCREMENT : INCREMENT);
  293. if (_deactivate) {
  294. deactivate(this);
  295. }
  296. else if (_count>1.0) {
  297. completeScaleTransition();
  298. }
  299. else if (_count<0.0) {
  300. completeReverseTransition();
  301. }
  302. }
  303. /**
  304. * Scale / cross-fade transition is complete
  305. */
  306. protected function completeScaleTransition():void {
  307. _count = 1.0;_deactivate = true;
  308. _screen.dispatchEvent(new Event(SCALE_COMPLETE));
  309. UI.uiLayer.visible = true;
  310. if (_window) {
  311. UI.windowLayer.visible = true;
  312. _window = null;
  313. }
  314. }
  315. /**
  316. * Inverse scale / cross-fade transition is complete
  317. */
  318. protected function completeReverseTransition():void {
  319. _count = 0.0;_deactivate = true;
  320. // deactivate(this);
  321. _screen.dispatchEvent(new Event(REVERSE_COMPLETE));
  322. UI.uiLayer.visible = true;
  323. }
  324. override public function destructor():void {
  325. super.destructor();
  326. _backgroundTextureBitMapData.dispose();
  327. _sourcePanelTextureBitMapData.dispose();
  328. _destinationPanelTextureBitMapData.dispose();
  329. }
  330. }
  331. }