package { import flash.display.Shader; import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import flash.filters.ShaderFilter; import flash.media.Camera; import flash.media.Video; import flash.ui.Keyboard; [SWF(width=640, height=480, backgroundColor=0x666666, frameRate=12)] /** * Demonstrates using user webcam input. In addition, this class uses a custom shader that distorts an * image like a funhouse mirror. Through the use of the keyboard, the user can alter * the parameters of the distortion applied. */ public class graphic_flex_image_effects_12_Flex_FunhouseMirror extends Sprite { // the width/height of the webcam image private static const MIRROR_WIDTH:uint = 640; private static const MIRROR_HEIGHT:uint = 480; private var _shaderProxy:graphic_flex_image_effects_12_Flex_ShaderProxy; private var _video:Video; /** * Constructor. This instantiates a ShaderProxy and passes a path to a shader file to load. */ public function graphic_flex_image_effects_12_Flex_FunhouseMirror() { // if you are using the Flex framework, you can embed the shader bytecode and pass // the class from the embed tag to this constructor _shaderProxy = new graphic_flex_image_effects_12_Flex_ShaderProxy("graphic-flex-image-effects-12-assets-funhouseMirror.pbj"); // if (default) you are passing a path to a .pbj file, wait for COMPLETE if (_shaderProxy.shader == null) { _shaderProxy.addEventListener(Event.COMPLETE, onShaderLoaded); // if bytecode was embedded, we can proceed immediately } else { createMirror(); } } /** * Grabs webcam input, if allowed, and sets up a Video instance to display its data. * The custom shader is applied as a filter to the video. */ private function createMirror():void { var camera:Camera = Camera.getCamera(); // does NOT handle messaging the user if no camera is available or allowed if (camera != null) { camera.setMode(MIRROR_WIDTH, MIRROR_HEIGHT, stage.frameRate); _video = new Video(MIRROR_WIDTH, MIRROR_HEIGHT); _video.attachCamera(camera); _video.filters = [new ShaderFilter(_shaderProxy.shader)]; addChild(_video); // keyboard event listener so shader parameters can be altered stage.addEventListener(KeyboardEvent.KEY_DOWN, onStageKeyDown); } } /** * Handler for when a key is pressed. This allows for altering the shader parameters. * * @param event Event dispatched by stage. */ private function onStageKeyDown(event:KeyboardEvent):void { // amount by which values should be changed var rate:Number = .05; // grab current values var rX:Number = _shaderProxy.warpRatioX; var rY:Number = _shaderProxy.warpRatioY; var dX:Number = _shaderProxy.distortionX; var dY:Number = _shaderProxy.distortionY; switch (event.keyCode) { case Keyboard.UP: // SHIFT is pressed, alter distortion if (event.shiftKey) { _shaderProxy.distortionY = Math.min(1, dY + rate); // else alter ratio position } else { _shaderProxy.warpRatioY = Math.max(0, rY - rate); } break; case Keyboard.DOWN: // SHIFT is pressed, alter distortion if (event.shiftKey) { _shaderProxy.distortionY = Math.max(0, dY - rate); // else alter ratio position } else { _shaderProxy.warpRatioY = Math.min(1, rY + rate); } break; case Keyboard.RIGHT: // SHIFT is pressed, alter distortion if (event.shiftKey) { _shaderProxy.distortionX = Math.min(1, dX + rate); // else alter ratio position } else { _shaderProxy.warpRatioX = Math.min(1, rX + rate); } break; case Keyboard.LEFT: // SHIFT is pressed, alter distortion if (event.shiftKey) { _shaderProxy.distortionX = Math.max(0, dX - rate); // else alter ratio position } else { _shaderProxy.warpRatioX = Math.max(0, rX - rate); } break; // if arrow keys were not pressed, don't update shader default: return; } // reapply shader with changes _video.filters = [new ShaderFilter(_shaderProxy.shader)]; } /** * Handler for when shader completes loading. * * @param event Event dispatched by ShaderProxy. */ private function onShaderLoaded(event:Event):void { _shaderProxy.removeEventListener(Event.COMPLETE, onShaderLoaded); // set end positions of warp based on mirror size _shaderProxy.warpEndX = MIRROR_WIDTH; _shaderProxy.warpEndY = MIRROR_HEIGHT; createMirror(); } } }