In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Kaleidoscope

mouse right click or Ctrl + click and
from context menu, select or save your image.
/**
 * Copyright Test_Dept ( http://wonderfl.net/user/Test_Dept )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3S8y
 */

//
// mouse right click or Ctrl + click and
// from context menu, select or save your image.
//
package {

	import flash.display.Sprite;

	/**
	 * Kaleidoscope
	 * @author Test Dept
	 */
	[SWF(backgroundColor="#ffffff", width="465", height="465")]
	public class Kaleidoscope extends Sprite {
		public function Kaleidoscope() {
			addChild(new KaleidoscopeImpl() );	
		}		
	}
}

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.ContextMenuEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Camera;
import flash.media.Video;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;

import mx.graphics.codec.PNGEncoder;

class KaleidoscopeImpl extends Sprite {

	private static const MAX_SIZE : int = 4096;

	private var _a : UIPoint;
	private var _b : UIPoint;
	private var _c : UIPoint;

	private var _bmp : BitmapData;

	private var _video : Video;

	private var _filename : String;

	private var _fileRef : FileReference;

	private var _markAlpha : Number;

	private var _idleCount : int;

	public function KaleidoscopeImpl() {
		addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
	}
	
	private function addedToStageHandler(event : Event) : void {
		
		var width : Number = stage.stageWidth;
		var height : Number = stage.stageHeight;
		
		addChild(_a = new UIPoint(0x000000, 10, height / 2, "a", true) );
		addChild(_b = new UIPoint(0x000000, width - 10, height / 2 - 40, "b", true) );
		addChild(_c = new UIPoint(0x000000, width / 2, height / 2, "c", true) );

		_markAlpha = 0;
		_idleCount = 0;

		_bmp = new BitmapData(width, height, false, 0xffffff);
		_bmp.draw(new RandomImage(width, height) );
		_filename = "IMG.IMG";

		var camera : Camera = Camera.getCamera();
		if (camera != null) {
			camera.setMode(width, height, 16, true);
			_video = new Video(camera.width, camera.height);
			_video.attachCamera(camera);
		} else {
			_video = null;
		}
		
        contextMenu = new ContextMenu();
        contextMenu.hideBuiltInItems();
        contextMenu.customItems.push(createMenuItem("Select Source Image", contextMenu_loadHandler) );
        contextMenu.customItems.push(createMenuItem("Save Image", contextMenu_saveHandler) );

		addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
		addEventListener(Event.ENTER_FRAME, enterFrameHandler);
	}

	private function createMenuItem(label : String, handler : Function) : ContextMenuItem {
        var menuItem : ContextMenuItem = new ContextMenuItem(label);
        menuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handler);
        return menuItem;
	}

	private function contextMenu_loadHandler(event : ContextMenuEvent) : void {
		_fileRef = new FileReference();
		_fileRef.browse([
			new FileFilter("Image Files", "*.jpg;*.png"),
			new FileFilter("All Files", "*.*"),
		]);
		_fileRef.addEventListener(Event.SELECT, _fileRef_selectHandler);	
	}
	
	private function _fileRef_selectHandler(event : Event) : void {
		_filename = _fileRef.name;
		_fileRef.load();
		_fileRef.addEventListener(Event.COMPLETE, _fileRef_load_completeHandler);
	}

	private function _fileRef_load_completeHandler(event : Event) : void {
		var loader : Loader = new Loader();
		loader.loadBytes(_fileRef.data);
		loader.contentLoaderInfo.addEventListener(Event.COMPLETE, upload_completeHandler);
	}
	
	private function upload_completeHandler(event : Event) : void {
		var loaderInfo : LoaderInfo = event.target as LoaderInfo;
		var bitmap : Bitmap = loaderInfo.content as Bitmap;
		_bmp = bitmap.bitmapData;
		_video = null;
	}
	
	private function contextMenu_saveHandler(event : ContextMenuEvent) : void {

		var sp : Sprite = new Sprite();
		var g : Graphics = sp.graphics;
		g.clear();
		draw(g);

		var scale : Number = 1 / getScale();
		var rect : Rectangle = sp.getBounds(sp);
		
		if (rect.width * scale > MAX_SIZE) {
			scale = MAX_SIZE / rect.width;
		}
		if (rect.height * scale > MAX_SIZE) {
			scale = MAX_SIZE / rect.height;
		}
		
		var bmp : BitmapData = new BitmapData(
			Math.min(rect.width * scale, MAX_SIZE),
			Math.min(rect.height * scale, MAX_SIZE),
			true, 0);
		bmp.draw(sp, new Matrix(scale, 0, 0, scale, -rect.x * scale, -rect.y * scale) );

		var match : Object = /^(.+)\..+$/.exec(_filename);
		
		var newFilename : String = match[1] + "_" + new Date().getTime() + ".png";
		var encoder : PNGEncoder = new PNGEncoder();

		_fileRef = new FileReference();
		_fileRef.save(encoder.encode(bmp), newFilename);
	}

	private function enterFrameHandler(event : Event) : void {

		if (_idleCount > 0) {
			_idleCount--;
		} else {
			_markAlpha = Math.max(0, _markAlpha - 0.04);
		}

		_a.alpha = _markAlpha;
		_b.alpha = _markAlpha;
		_c.alpha = _markAlpha;

		if (_video != null) {
			_bmp.draw(_video, new Matrix(_video.scaleX, 0, 0, _video.scaleY) );
		}

		var g : Graphics = graphics;
		g.clear();
		g.lineStyle(1, 0x000000, _markAlpha);
		draw(g);
	}
	
	private function draw(g : Graphics) : void {

		var a : Point = new Point(_a.x, _a.y);
		var b : Point = new Point(_b.x, _b.y);
		var c : Point = new Point(_c.x, _c.y);

		var o : Point = GeoUtil.getCenter(a, b, c);
				
		var ref_c : Point = GeoUtil.getCRef(a, b, c);

		var p_bc : Point = GeoUtil.getCrossPoint(o, a, b, ref_c);
		var p_ac : Point = GeoUtil.getCrossPoint(o, b, a, ref_c);
		
		var new_c : Point;
		
		if (p_bc != null) {
			new_c = p_bc;	
		} else if (p_ac != null) {
			new_c = p_ac;	
		} else {
			new_c = ref_c;
		}

		var scale : Number = getScale();

		var ksImage : KaleidoscopeImage = new KaleidoscopeImage(
			_bmp.width * scale, _bmp.height * scale);
		g.beginBitmapFill(_bmp);
		ksImage.draw(g, o, a, b, c);
		g.endFill();
	}
	
	private function getScale() : Number {
		return (_bmp.width / _bmp.height > stage.stageWidth / stage.stageHeight)?
			stage.stageWidth / _bmp.width : stage.stageHeight / _bmp.height;			
	}
	
	private function mouseMoveHandler(event : Event) : void {
		_markAlpha = 0.5;
		_idleCount = 20;
	}
}

class KaleidoscopeImage {

	private var _width : Number;
	private var _height : Number;

	private var _maxNest : int;
	
	private var _o : Point;
	
	private var _vertices : Vector.<Number>;
	private var _indices : Vector.<int>;
	private var _uvtData : Vector.<Number>;
	
	public function KaleidoscopeImage(width : Number, height : Number, maxNest : int = 16) {
		_width = width;
		_height = height;
		_maxNest = maxNest;
	}

	public function draw(g : Graphics, o : Point, a : Point, b : Point, c : Point) : void {

		_o = o;
					
		_vertices = new Vector.<Number>();
		_indices = new Vector.<int>();
		_uvtData = new Vector.<Number>();

		 var t : Point = get_uvt(a);
		 var u : Point = get_uvt(b);
		 var v : Point = get_uvt(c);
		
		addTriangle(a, b, c, t, u, v);
				 
		reflect(a, b, c, t, u, v, 0);
		reflect(b, c, a, u, v, t, 0);
		reflect(c, a, b, v, t, u, 0);

		g.drawTriangles(_vertices, null, _uvtData);
	}
	
	private function reflect(
		a : Point, b : Point, c : Point,
		t : Point, u : Point, v : Point,
		nest : int
	) : void {

		if (nest > _maxNest) {
			return;
		}

		if (!isVisible(a, b, c) ) {
			return;
		}

		var ref_c : Point = GeoUtil.getCRef(a, b, c);

		var c_bc : Point = GeoUtil.getCrossPoint(_o, a, b, ref_c);
		var c_ac : Point = GeoUtil.getCrossPoint(_o, b, a, ref_c);

		var new_c : Point;
		if (c_bc != null) {
			new_c = c_bc;
		} else if (c_ac != null) {
			new_c = c_ac;
		} else {
			new_c = ref_c;
		}

		var new_v : Point = GeoUtil.createTransformMatrix(a, b, ref_c, t, u, v)
			.transformPoint(new_c);
		
		addTriangle(a, b, new_c, t, u, new_v);

		if (c_bc == null) {
			reflect(new_c, a, b, new_v, t, u, nest + 1);
		}
		if (c_ac == null) {
			reflect(new_c, b, a, new_v, u, t, nest + 1);
		}
	}

	private function addTriangle(
		a : Point, b : Point, c : Point,
		t : Point, u : Point, v : Point
	) : void {
		_vertices.push(a.x, a.y, b.x, b.y, c.x, c.y);
		_indices.push(0, 1, 2);
		_uvtData.push(t.x, t.y, u.x, u.y, v.x, v.y);
	}	
	
	private function get_uvt(p : Point) : Point {
		return new Point(p.x / _width, p.y / _height);		
	}
	
	private function isVisible(a : Point, b : Point, c : Point) : Boolean {

		var minX : Number = Math.min(a.x, b.x, c.x);
		var minY : Number = Math.min(a.y, b.y, c.y);
		var maxX : Number = Math.max(a.x, b.x, c.x);
		var maxY : Number = Math.max(a.y, b.y, c.y);
		
		var r1 : Rectangle = new Rectangle(
			0, 0, _width, _height);

		var r2 : Rectangle = new Rectangle(
			minX, minY, maxX - minX, maxY - minY);

		return r1.intersects(r2);
	}
}

class RandomImage extends Sprite {

	public function RandomImage(width : Number, height : Number) {

		var colors : Array = [
			0xff0000,
			0xffff00,
			0x00ff00,
			0x00ffff,
			0x0000ff,
			0xff00ff
		];
		
//		var rand : Function = Math.random;
		var rand : Function = FakeRand.random;

		var g : Graphics = graphics;
		
		g.clear();
		
		for (var i : int = 0; i < 100; i++) {

			var x : Number = rand() * width;
			var y : Number = rand() * height;
			var r : Number = rand() * 50 + 10;
			var c : uint = colors[i % colors.length];

			g.beginFill(c, 0.4);
			g.drawCircle(x, y, r);
			g.endFill();
		}
	}
}

class FakeRand {

	private var _num : Number;
	private var _digits : int;
	
	public function FakeRand(seed : Number = 0, digits : int = 10000) {
		_num = Math.exp(seed);
		_digits = digits;
	}
	
	public function next() : Number {
		_num = _num * _digits + Math.PI;
		_num = _num - Math.floor(_num);
		return int(_num * _digits) % _digits / _digits;
	}
	
	private static var _instance : FakeRand = new FakeRand();
	
	public static function random() : Number {
		return _instance.next();
	}
}

class GeoUtil {

	public static function getCenter(
		a : Point, b : Point, c : Point
	) : Point {

		var bc : Point = new Point(
			(b.x + c.x) / 2,
			(b.y + c.y) / 2);

		return new Point(
			a.x + (bc.x - a.x) * 2 / 3,
			a.y + (bc.y - a.y) * 2 / 3);		
	}

	public static function createMatrix(
		a : Point, b : Point, c : Point,
		invert : Boolean = false
	) : Matrix {

		var m : Matrix = new Matrix(
			b.x - a.x, b.y - a.y,
			c.x - a.x, c.y - a.y);

		if (invert) {
			m.invert();
		}

		return m;
	}
	
	public static function createTransformMatrix(
		a : Point, b : Point, c : Point,
		t : Point, u : Point, v : Point
	) : Matrix {

		var m1 : Matrix = new Matrix();
		m1.translate(-a.x, -a.y);
		m1.concat(createMatrix(a, b, c, true) );
		m1.concat(createMatrix(t, u, v) );
		m1.translate(t.x, t.y);
		
		return m1;
	} 

	public static function getCRef(
		a : Point, b : Point, c : Point
	) : Point {

		var m1 : Matrix = new Matrix();
		var m2 : Matrix = new Matrix(
			b.x - a.x, b.y - a.y, a.y - b.y, b.x - a.x);
		var m3 : Matrix = new Matrix(1, 0, 0, -1);

		m1.translate(-a.x, -a.y);
		
		m2.invert();
		m1.concat(m2);
		
		m1.concat(m3);
		
		m2.invert();
		m1.concat(m2);
		
		m1.translate(a.x, a.y);
		
		return m1.transformPoint(new Point(c.x, c.y) );
	}
	
	public static function getCrossPoint(
		o : Point,
		a : Point, b : Point, c : Point
	) : Point {
		
		var mat : Matrix = new Matrix(
			a.x - o.x, a.y - o.y,
			c.x - b.x, c.y - b.y);
		
		mat.invert();
		
		var st : Point = mat.transformPoint(b.subtract(o) );
		
		var s : Number = st.x;
		var t : Number = -st.y;
		
		if (0 <= t && t <= 1) {
			return new Point(
				o.x + (a.x - o.x) * s,
				o.y + (a.y - o.y) * s);
		} else {
			return null;
		}
	}
}

class UIPoint extends Sprite {

	private var _pressed : Boolean;
	private var _dragX : Number;
	private var _dragY : Number;
	
	public function UIPoint(
		color : uint, x : Number, y : Number, label : String,
		movable : Boolean = false
	) {

		var g : Graphics = graphics;
		g.clear();
		g.lineStyle(2, 0xffffff ^ color);
		g.beginFill(color);
		g.drawCircle(0, 0, 5);
		g.endFill();
		
		var labelField : TextField = new TextField();
		labelField.type = TextFieldType.DYNAMIC;
		labelField.autoSize = TextFieldAutoSize.LEFT;
		labelField.selectable = false;
		labelField.text = label;
		labelField.x = 4;
		labelField.y = 4;
		addChild(labelField);

		this.x = x;
		this.y = y;
		
		buttonMode = movable;
		useHandCursor = movable;

		if (movable) {
			_pressed = false;
			addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);	
		}
	}
	
	private function mouseDownHandler(event : MouseEvent) : void {

		if (_pressed) return;
		
		stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
		stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
		stage.addEventListener(Event.MOUSE_LEAVE, stage_mouseLeaveHandler);

		_dragX = mouseX;
		_dragY = mouseY;
		_pressed = true;
	}

	private function stage_mouseMoveHandler(event : MouseEvent) : void {
		x += (mouseX - _dragX);
		y += (mouseY - _dragY);
	}
	
	private function stage_mouseUpHandler(event : MouseEvent) : void {
		releaseMouse();
	}
	
	private function stage_mouseLeaveHandler(event : Event) : void {
		releaseMouse();
	}

	private function releaseMouse() : void {

		if (!_pressed) return;

		stage.removeEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
		stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
		stage.removeEventListener(Event.MOUSE_LEAVE, stage_mouseLeaveHandler);
		
		_pressed = false;
	}
}