How to fix localToGlobal when not providing global coordinates? - actionscript-3

I created dynamically 5 boxes that are stacked next to each other on the stage. The first one is located at (0,0), next one at (100,0), the third one on (200,0) and so on.
The problem I am having is that every time I click on each individual box, it traces that it is at (0,0). I tried using localToGlobal but to no avail.
Here is what I tried:
I tried attaching an event listener to each box so that I can take the local coordinates and get their global equivalents but that failed.
import com.mahmoud.util.drawLabel;
import flash.geom.Point;
import flash.events.MouseEvent;
var d: drawLabel;
var global: Point;
for (var i: uint = 0; i < 5; i++) {
d = new drawLabel();
d.init(i, "", "", 100, 75, i * 101, 0);
d.addEventListener(MouseEvent.CLICK, check);
addChild(d);
}
function check(e: MouseEvent): void {
global = new Point(drawLabel(e.currentTarget).x,drawLabel(e.currentTarget).y)
trace(drawLabel(e.currentTarget).localToGlobal(global));
}
UPDATE: this is what's in drawLabel
package com.mahmoud.util {
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.GradientType;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.text.TextFormat;
import com.mahmoud.util.xScroll;
import com.greensock.events.LoaderEvent;
import com.greensock.loading.core.DisplayObjectLoader;
import com.greensock.loading.core.LoaderItem;
import com.greensock.loading.ImageLoader;
import com.greensock.TweenLite;
import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.ProgressEvent;
public class drawLabel extends Sprite {
private var bc: Sprite;
private var label_txt: TextField;
private var theSentence: String;
private var loader: ImageLoader;
private var f: TextFormat = new TextFormat("Arial", 15, null, null, null, null, null, null);
public var idArray: Array = new Array("default value");
public function drawLabel() {}
public function init(theSentence, whatFmt, iconOf, labelWidth: Number = 100, labelHeight: Number = 50, label_x: Number = 0, label_y: Number = 0, colorOf: uint = 0xEFEFEF, alphaOf: Number = 1, inputType: String = "dynamic", inputSelectable: Boolean = false, idArray: Array = null, factorX: Number = 100, factorY: Number = 75, iconOfScale: String = "", backUpImage: String = "", imageRatio: uint = 2) {
bc = new Sprite;
bc.tabEnabled = true
label_txt = new TextField;
bc.graphics.beginFill(colorOf, alphaOf);
bc.graphics.drawRect(label_x, label_y, labelWidth, labelHeight);
bc.graphics.endFill();
bc.mouseChildren = true;
bc.buttonMode = true;
//center text within the box
label_txt.width = factorX * (labelWidth / 100);
label_txt.height = factorY * (labelHeight / 100);
label_txt.x = (labelWidth / 2 - ((factorX * (labelWidth / 100)) / 2)) + label_x
label_txt.y = (labelHeight / 2 - ((factorY * (labelHeight / 100)) / 2)) + label_y
label_txt.multiline = true;
label_txt.wordWrap = true;
label_txt.border = true;
label_txt.type = inputType
label_txt.selectable = inputSelectable;
label_txt.text = theSentence;
label_txt.embedFonts = false;
label_txt.tabIndex = 0
if (whatFmt == "") {
whatFmt = f
}
label_txt.setTextFormat(whatFmt);
bc.addChild(label_txt);
addChild(bc);
//load the image and attach it to bc. create an ImageLoader using greensock
//the image is optional, so check the text to see if it is not null
if (iconOf !== "") {
if (iconOfScale == "") {
iconOfScale = "proportionalInside"
}
loader = new ImageLoader(iconOf, {
name: "icon_",
container: this,
x: label_x + labelWidth - (33),
y: label_y + labelHeight / 2,
width: labelWidth / imageRatio,
height: labelHeight / imageRatio,
scaleMode: iconOfScale,
centerRegistration: true,
alternateURL: backUpImage,
onComplete: onImageLoad,
onError: fileNotFound
});
//begin loading
loader.load();
//when the image loads, fade it in from alpha:0 using TweenLite
function onImageLoad(event: LoaderEvent): void {
TweenLite.from(event.target.content, 1, {
alpha: 0
});
}
function fileNotFound(event: LoaderEvent): void {
trace("image missing")
}
}
}
}
}
Any help is appreciated,
thank you

The problem I am having is that every time I click on each individual
box, it traces that it is at (0,0). I tried using localToGlobal but
to no avail.
Another option (avoiding localToGlobal) is to just use target.x and target.y.
This will allow you to target each individual box.
example code:
for (var i: uint = 0; i < 5; i++)
{
d = new drawLabel();
d.init(i, "", "", 100, 75, i * 100, 0);
d.name = "label_" + i; //# give each one a name if you want to...
d.addEventListener(MouseEvent.CLICK, check);
addChild(d);
}
Then check like so... (note: use currentTarget for name, but then use target for x/y for position).
function check(e: MouseEvent): void
{
trace( " " + "\n" + "# Got checking click" + "\n" + "-----------------------");
trace( "Name : " + e.currentTarget.name);
trace( "Pos : " + "{ x: " + e.target.x + ", y: " + e.target.y + " }" );
}

You are trying to localToGlobal your drawLabel class, which is at 0,0. The box inside the class, is at 100/200/300/etc... You should be trying to localToGlobal on the box, not the Class. Or you can simply move the class and continue to track the class instead to simplify things.
drawLabel:
bc.graphics.drawRect(0, 0, labelWidth, labelHeight);
this.x = label_x;
this.y = label_y;
Main:
trace(e.currentTarget.x + ', ' + e.currentTarget.y);
If for any reason you need drawLabel to be at 0,0 and move the box inside it instead, simply do this.
drawLabel:
public var bc: Sprite;
Main:
trace(e.currentTarget.bc.x + ', ' + e.currentTarget.bc.y);

Related

Scrolling on mobile devices using AS3 AIR?

I have generated the XML calling button into a movie clip.
Here Is Code
import flash.display.MovieClip;
import com.greensock.*;
import com.greensock.easing.*;
import com.greensock.plugins.*;
import flash.geom.Rectangle;
import flash.utils.getTimer;
import flash.events.MouseEvent;
import flash.text.*;
import flash.display.*;
TweenPlugin.activate([ThrowPropsPlugin]);
var Buttons = new Button_mc();
var across: int = 2;
function generatebtn() {
for (var i = 0; i < buttonno; i++) {
Buttons = new Button_mc();
Buttons.name = "Button" + i;
Buttons.TypeofQuestions.text = Gk_mc.storeQuesType[i];
var row: int = Math.floor(i / across);
var col: int = i % 2;
MyMovieClip.mc_2.addChild(Buttons);
Buttons.x = col * (Buttons.width) + 25;
Buttons.y = row * (Buttons.height);
Buttons.buttonMode = true;
Buttons.addEventListener(MouseEvent.CLICK, accessclicking);
}
function accessclicking(e: Event): void {
trace(e.currentTarget.name);
}
}
generatebtn();
It's properly working with button clicking Event.
When I add more code the buttons clicking Function doesn't work. See below code:
// ----- set up masking boundary for list ------ //
var bounds: Rectangle = new Rectangle(0, 0, MyMovieClip.mc_2.width, 600);
var blitMask: BlitMask = new BlitMask(MyMovieClip.mc_2, bounds.x, bounds.y, bounds.width, bounds.height, false);
var t1: uint, t2: uint, y1: Number, y2: Number, yOverlap: Number, yOffset: Number;
blitMask.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(event: MouseEvent): void {
TweenLite.killTweensOf(MyMovieClip.mc_2);
y1 = y2 = MyMovieClip.mc_2.y;
yOffset = this.mouseY - MyMovieClip.mc_2.y;
yOverlap = Math.max(0, MyMovieClip.mc_2.height - bounds.height);
t1 = t2 = getTimer();
MyMovieClip.mc_2.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
MyMovieClip.mc_2.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
function mouseMoveHandler(event: MouseEvent): void {
var y: Number = this.mouseY - yOffset;
// ----- mc's position exceeds the bounds, make it drag only half as far with each mouse movement (like iPhone/iPad behavior) ------ //
if (y > bounds.top) {
MyMovieClip.mc_2.y = (y + bounds.top) * 0.5;
} else if (y < bounds.top - yOverlap) {
MyMovieClip.mc_2.y = (y + bounds.top - yOverlap) * 0.5;
} else {
MyMovieClip.mc_2.y = y;
}
blitMask.update();
var t: uint = getTimer();
// -----If the frame rate is too high, we won't be able to track the velocity as well, so only update the values 20 times per second ------ //
if (t - t2 > 50) {
y2 = y1;
t2 = t1;
y1 = MyMovieClip.mc_2.y;
t1 = t;
}
event.updateAfterEvent();
}
function mouseUpHandler(event: MouseEvent): void {
MyMovieClip.mc_2.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
MyMovieClip.mc_2.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
var time: Number = (getTimer() - t2) / 1000;
var yVelocity: Number = (MyMovieClip.mc_2.y - y2) / time;
ThrowPropsPlugin.to(MyMovieClip.mc_2, {
throwProps: {
y: {
velocity: yVelocity,
max: bounds.top,
min: bounds.top - yOverlap,
resistance: 300
}
},
onUpdate: blitMask.update,
ease: Strong.easeOut
},
10, 0.3, 1);
}
/* Drag and Drop
Makes the specified symbol instance move-able with drag and drop.
*/
MyMovieClip.mc_2.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag);
function fl_ClickToDrag(event: MouseEvent): void {
MyMovieClip.mc_2.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
function fl_ReleaseToDrop(event: MouseEvent): void {
MyMovieClip.mc_2.stopDrag();
}
Scrolling works properly but I want to do scrolling via clicking buttons It's a long-time problem 6 months ago, but it's still not solved.
I'm going to assume your buttons are below the blitMask.
You can make mouse events fall through any DisplayObject by settings its mouseEnabled property to false
blitMask.mouseEnabled = false;

AS3 Softbody texture starling

I have created a soft body circle in nape. And now I'm trying to get it texturized. But I'm having trouble, and I can't find the answer. Thats why I'm turning to you guys.
Im trying to do what he is doing in this objective c tutorial:
http://www.uchidacoonga.com/2012/04/soft-body-physics-with-box2d-and-cocos2d-part-44/
any ideas on how to do this with starling and stage3d?
You have to write a custom display object (see Starling manual). Here's a basic example:
package
{
import com.adobe.utils.AGALMiniAssembler;
import flash.display3D.Context3D;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.VertexBuffer3D;
import flash.geom.Point;
import flash.utils.ByteArray;
import starling.core.RenderSupport;
import starling.core.Starling;
import starling.display.DisplayObject;
import starling.errors.MissingContextError;
import starling.textures.Texture;
public class Ball extends DisplayObject
{
private static const PROGRAM_NAME:String = "ball";
private var _texture:Texture;
private var _numSides:uint;
private static const data32PerVertex:uint = 4;
private var _vertices:Vector.<Number>;
private var _indices:Vector.<uint>;
private var _vertexBuffer:VertexBuffer3D;
private var _indexBuffer:IndexBuffer3D;
public function Ball(initialX:Number, initialY:Number, initialR:Number, texture:Texture, numSides:uint = 10) {
_texture = texture;
_numSides = numSides;
// if the texture is a SubTexture (i.e. a texture from an atlas), then you need
// to modify these values to match the sub-texture UV bounds.
var minU:Number = 0, minV:Number = 0, maxU:Number = 1, maxV:Number = 1;
setupGeometry(initialX, initialY, initialR, minU, minV, maxU, maxV);
createBuffers();
registerPrograms();
}
private function setupGeometry(initialX:Number, initialY:Number, initialR:Number, uMin:Number, vMin:Number, uMax:Number, vMax:Number):void {
const numVertices:uint = _numSides + 1,
numSideVertices:uint = _numSides,
txtCu:Number = (uMin + uMax) / 2, // center of the circle in UV coords
txtCv:Number = (vMin + vMax) / 2,
txtRu:Number = uMax - txtCu, // radiuses of the circle in UV coords
txtRv:Number = vMax - txtCv;
_vertices = new Vector.<Number>(data32PerVertex * numVertices, true);
_indices = new Vector.<uint>(3 * _numSides, true);
var centerVectexIndex:uint = _numSides;
// side vertices
for (var sideVertexI:uint = 0; sideVertexI < numSideVertices; ++sideVertexI) {
var dataOffset:uint = sideVertexI * data32PerVertex,
angle:Number = 2 * Math.PI * sideVertexI / _numSides,
sinA:Number = Math.sin(angle),
cosA:Number = Math.cos(angle);
_vertices[dataOffset ] = initialX + initialR * cosA; // x
_vertices[dataOffset + 1] = initialY + initialR * sinA; // y
_vertices[dataOffset + 2] = txtCu + txtRu * cosA; // u
_vertices[dataOffset + 3] = txtCv + txtRv * sinA; // v
var indexOffset:uint = 3 * sideVertexI;
_indices[indexOffset ] = centerVectexIndex;
_indices[indexOffset + 1] = sideVertexI;
_indices[indexOffset + 2] = (sideVertexI + 1) % numSideVertices;
}
// center vertex
dataOffset = centerVectexIndex * data32PerVertex;
_vertices[dataOffset ] = initialX; // x
_vertices[dataOffset + 1] = initialY; // y
_vertices[dataOffset + 2] = txtCu; // u
_vertices[dataOffset + 3] = txtCv; // v
}
private function createBuffers():void {
var context:Context3D = Starling.context;
if (context == null) {
throw new MissingContextError();
}
_vertexBuffer && _vertexBuffer.dispose();
_indexBuffer && _indexBuffer.dispose();
const verticesCount:uint = _numSides + 1;
_vertexBuffer = context.createVertexBuffer(verticesCount, 4);
_vertexBuffer.uploadFromVector(_vertices, 0, verticesCount);
const indicesCount:uint = 3 * _numSides; // _numSides triangles, 3 indices per each triangle
_indexBuffer = context.createIndexBuffer(indicesCount);
_indexBuffer.uploadFromVector(_indices, 0, indicesCount);
}
private function registerPrograms():void {
var starling:Starling = Starling.current;
if (starling.hasProgram(PROGRAM_NAME)) {
return;
}
// va0.xy - position
// va1.xy - UV coords
// vc0-vc3 - mvp matrix
var vertexAGAL:String =
"m44 op, va0, vc0 \n" +
"mov v0, va1";
var fragmentAGAL:String =
"tex oc, v0, fs0 <2d, clamp, linear, mipnone> \n"; // just sample texture color
var asm:AGALMiniAssembler = new AGALMiniAssembler(),
vertexBytecode:ByteArray = asm.assemble(Context3DProgramType.VERTEX, vertexAGAL),
fragmentBytecode:ByteArray = asm.assemble(Context3DProgramType.FRAGMENT, fragmentAGAL);
starling.registerProgram(PROGRAM_NAME, vertexBytecode, fragmentBytecode);
}
override public function render(support:RenderSupport, parentAlpha:Number):void {
var context:Context3D = Starling.context;
if (context == null) {
throw new MissingContextError();
}
support.finishQuadBatch();
// setup
support.applyBlendMode(_texture.premultipliedAlpha);
context.setProgram(Starling.current.getProgram(PROGRAM_NAME));
context.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2); // position, va0
context.setVertexBufferAt(1, _vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2); // uv, va1
context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, support.mvpMatrix3D, true); // mvp matrix, vc0-vc3
context.setTextureAt(0, _texture.base); // texture, fs0
// draw
context.drawTriangles(_indexBuffer);
support.raiseDrawCount();
// clean up
context.setVertexBufferAt(0, null);
context.setVertexBufferAt(1, null);
context.setTextureAt(0, null);
}
override public function hitTest(localPoint:Point, forTouch:Boolean = false):DisplayObject {
var isHit:Boolean = false;
// to achieve proper mouse handling, you need to place here the code
// that checks if localPoint is contained inside any of triangles and
// sets isHit flag accorgingly.
return isHit ? this : null;
}
}
}
Usage example:
package
{
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.geom.Matrix;
import starling.display.Sprite;
import starling.textures.Texture;
public class BallExperiment extends starling.display.Sprite
{
public function BallExperiment() {
}
public function start():void {
const numSides:uint = 7;
var txt:Texture = createBallTxt(numSides, true);
var ball:Ball = new Ball(200, 200, 50, txt, numSides);
addChild(ball);
}
private function createBallTxt(numSides:uint, debugFillBcgr:Boolean = false):Texture {
var canvas:flash.display.Sprite = new flash.display.Sprite(),
g:Graphics = canvas.graphics;
// as we don't want to use sub-textures in this simple example, we need this
// number to be a power of two: otherwise Starling will internally create
// a power-of-two-sized texture and return a sub-texture of this bigger texture.
const size:Number = 512;
// we need to make the radius of a ball texture to be smaller than size/2 in order
// to prevent the texture from extending beyond our triangles.
var rScale:Number = Math.cos(Math.PI / numSides),
r:Number = rScale * (size / 2);
g.lineStyle(0, 0, 0);
// draw uniform background to show actual triangulation
if (debugFillBcgr) {
g.beginFill(0xBB4400, 0.2);
g.drawRect(0, 0, size, size);
g.endFill();
}
// draw the ball
g.beginFill(0x0000DD);
g.drawCircle(size / 2, size / 2, r);
var m:Matrix = new Matrix();
m.createGradientBox(size, size);
g.beginGradientFill(GradientType.LINEAR, [0x00DD00, 0x00DD00], [0, 1], [0, 255], m);
g.drawCircle(size / 2, size / 2, r);
g.endFill();
const smallCircleR:Number = r / 10,
smallCircleCR:Number = r - 2 * smallCircleR;
g.beginFill(0xBB0000);
for (var i:uint = 0; i < numSides; ++i) {
var angle:Number = 2 * Math.PI * i / numSides,
cx:Number = size / 2 + smallCircleCR * Math.cos(angle),
cy:Number = size / 2 + smallCircleCR * Math.sin(angle);
g.drawCircle(cx, cy, smallCircleR);
}
g.drawCircle(size / 2, size / 2, smallCircleR);
g.endFill();
// create and return the texture
var bmd:BitmapData = new BitmapData(size, size, true, 0);
bmd.draw(canvas);
return Texture.fromBitmapData(bmd);
}
}
}
Example runner:
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import starling.core.Starling;
import starling.events.Event;
[SWF(width = 600, height = 500, frameRate = 60)]
public class StarlingTestRunner extends Sprite
{
public function StarlingTestRunner() {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
Starling.multitouchEnabled = false;
Starling.handleLostContext = false;
var starling:Starling = new Starling(BallExperiment, stage);
starling.showStats = true;
starling.simulateMultitouch = true;
starling.enableErrorChecking = true;
starling.addEventListener(Event.ROOT_CREATED, onTestCreated);
starling.start();
}
private function onTestCreated(e:Event, test:BallExperiment):void {
test.start();
}
}
}
The result:
To distort the ball, just modify those elements of _vertices vector that correspond to x and y coordinates (i.e. elements with indices 4n and 4n + 1, where n = 0 .. numSides) and then re-upload _vertices array to the vertex buffer.
Alternatively, you can implement ball geometry using VertexData helper class, as shown in Starling manual.

How do I create a Swirl effect in AS3?

I want to manipulate and animate some BitmapData to create a swirl effect such as the one found in the link below:
http://www.flash-filter.net/swirl-effect.phtml
What techniques could I apply?
Btw: Yes, I do know the effect is ugly..
In case you're looking for how a swirl effect is achieved, i.e. the algorithm. Here is a nice step-by-step explanation of how the image is transformed: Image- Twist and Swirl Algorithm
There is a Pixel Bender filter for this. Check out this link:
http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&extid=1536021
Here is a tutorial on Tweening Pixel Bender filters
http://plasticsturgeon.com/2011/03/pixel-transition-tweening-a-pixel-bender-filter-in-as3/
You may also want to check out the AS3 ImageProcessing library
http://blog.joa-ebert.com/imageprocessing-library/
This should give you a good starting point
Pixel Bender ist krieg!
While I do agree with the previous answers, I'd like to point out, that you can do this kind of effect by using only bitmap filters that are out there for years now: DisplacementMapFilter namely. Create a displacement map that moves pixels in a circular direction and apply this map to an image multiple times. This will get you a swirling transformation.
Here's my simple implementation.
The usage is pretty straightforward (see after the class).
package org.noregret.images
{
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.InterpolationMethod;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* #author Nox Noctis (http://noregret.org)
*/
public class Swirl
{
public var target : DisplayObject;
public var allowCache : Boolean = false;
public var levels : uint;
public var isDestroyed : Boolean;
protected var bitmapMargin : Point;
protected var filter : DisplacementMapFilter;
protected var radius : int;
protected var cache : Object;
protected var map : BitmapData;
protected var targetRect : Rectangle;
protected var mapOffset : Point;
protected var maxLevel : Number = 1;
public function Swirl(_target : DisplayObject, _filterLevels : uint = 10, _allowCache : Boolean = true)
{
target = _target;
allowCache = _allowCache;
levels = _filterLevels;
cache = {};
filter = new DisplacementMapFilter();
filter.componentX = BitmapDataChannel.RED;
filter.componentY = BitmapDataChannel.GREEN;
filter.scaleX = -20;
filter.scaleY = -20;
filter.mapPoint = new Point();
filter.mode = DisplacementMapFilterMode.IGNORE;
}
private function createDisplacementMap() : void
{
targetRect = target.getRect(target);
radius = Math.max(Math.max(targetRect.width, targetRect.height), 100) / 2;
radius = Math.sqrt(2) * radius;
mapOffset = new Point(radius - targetRect.width / 2, radius - targetRect.height / 2);
var mapSprite : Sprite = new Sprite();
var redLayer : Sprite = new Sprite();
var greenLayer : Sprite = new Sprite();
var grayLayer : Sprite = new Sprite();
mapSprite.addChild(redLayer);
mapSprite.addChild(greenLayer);
mapSprite.addChild(grayLayer);
var gradientMatrix : Matrix;
gradientMatrix = new Matrix();
gradientMatrix.createGradientBox(radius * 2, radius * 2, Math.PI / 2, -radius, -radius);
redLayer.graphics.lineStyle(0, 0, 0);
redLayer.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0], [100, 100], [0, 255], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);
redLayer.graphics.drawCircle(0, 0, radius);
redLayer.graphics.endFill();
greenLayer.graphics.lineStyle(0, 0, 0);
gradientMatrix.createGradientBox(radius * 2, radius * 2, 0, -radius, -radius);
greenLayer.graphics.beginGradientFill(GradientType.LINEAR, [0x00FF00, 0x00FF00], [0, 100], [10, 245], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);
greenLayer.graphics.drawCircle(0, 0, radius);
greenLayer.graphics.endFill();
greenLayer.blendMode = BlendMode.ADD;
gradientMatrix = new Matrix();
gradientMatrix.createGradientBox(radius * 2, radius * 2, 0, -radius, -radius);
grayLayer.graphics.lineStyle(0, 0, 0);
grayLayer.graphics.beginGradientFill(GradientType.RADIAL, [0x808080, 0x808080], [0, 100], [0, 0xFF], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);
grayLayer.graphics.drawCircle(0, 0, radius);
grayLayer.graphics.endFill();
var rect : Rectangle = mapSprite.getRect(mapSprite);
var matrix : Matrix = new Matrix();
matrix.translate(-rect.x, -rect.y);
if (map) {
map.dispose();
}
map = new BitmapData(rect.width, rect.height, false, 0xFF808080);
map.draw(mapSprite, matrix);
filter.mapBitmap = map;
}
public function swirlTo(ratio : Number) : BitmapData
{
if (isDestroyed) {
trace("Swirl: error! Tried to swirl on disposed item.");
return null;
}
if (ratio < 0) {
ratio = 0;
}
var level : uint = Math.round(levels * ratio);
var cacheName : String = getCacheName(level);
if (cache[cacheName]) {
return (cache[cacheName] as BitmapData).clone();
}
var rect : Rectangle = target.getRect(target);
if (!map || rect.width != targetRect.width || rect.height != targetRect.height) {
createDisplacementMap();
flushCache();
}
var point : Point = new Point(-targetRect.x, -targetRect.y);
bitmapMargin = new Point(point.x + mapOffset.x, point.y + mapOffset.y);
var bmp : BitmapData;
if (cache["l" + maxLevel]) {
bmp = cache["l" + maxLevel] as BitmapData;
} else {
bmp = new BitmapData(map.width, map.height, true, 0);
var matrix : Matrix = new Matrix();
matrix.translate(bitmapMargin.x, bitmapMargin.y);
bmp.draw(target, matrix, null, null, null, true);
}
if (level == 0) {
cache[cacheName] = bmp.clone();
return bmp;
}
var destPoint : Point = new Point();
for (var i : Number = maxLevel;i <= level; i++) {
bmp.applyFilter(bmp, bmp.rect, destPoint, filter);
if (allowCache) {
cache["l" + i] = bmp.clone();
}
}
maxLevel = Math.max(maxLevel, level);
return bmp;
}
private function getCacheName(level : uint) : String
{
return "l" + level;
}
public function flushCache() : void
{
for each (var bmp:BitmapData in cache) {
bmp.dispose();
}
cache = {};
}
public function destroy() : void
{
flushCache();
target = null;
map.dispose();
map = null;
isDestroyed = true;
}
}
}
Usage example:
package
{
import flash.display.Sprite;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.display.Bitmap;
import org.noregret.images.Swirl;
[SWF(width="800",height="600",backgroundColor="#FFFFFF",fps="30")]
public class TestSwirl extends Sprite
{
private const loader:Loader = new Loader();
private const swirlBitmap:Bitmap = new Bitmap();
private var swirl:Swirl;
private var time:Number = 0;
public function TestSwirl()
{
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
var request:URLRequest = new URLRequest("http://i.stack.imgur.com/Vtsvm.gif");
loader.load(request, new LoaderContext(true));
}
protected function onLoadComplete(event:Event):void
{
var original:Bitmap = loader.content as Bitmap;
addChild(original);
swirlBitmap.bitmapData = original.bitmapData.clone();
swirlBitmap.x = original.x + original.width + 10;
addChild(swirlBitmap);
swirl = new Swirl(original,80);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
protected function onEnterFrame(event:Event):void
{
var ratio:Number = Math.abs(Math.sin(time));
// ***
swirlBitmap.bitmapData = swirl.swirlTo(ratio);
// ***
time += .02;
}
}
}
I would suggest using Pixel Bender to create your own bitmap filters.

AS3 playback of sound byte array doesn't begin at the start

I'm currently recording and storing a ByteArray of sound and then playing it back. But for some reason the playback starting position of the ByteArray is 163840, not 0 as I need it to be.
Would anyone have any ideas why this might be happening?
Thanks,
Mark
var soundBA:ByteArray = new ByteArray();
var sound:Sound = new Sound();
var ch:SoundChannel = new SoundChannel();
var recordingsArray:Array = new Array();
//imagine I have successfully recorded and stored the sound into recordingsArray
soundBA.clear();
soundBA.length = 0;
//I collect the recorded byteArray within an array
soundBA.writeBytes(recordingsArray[0]);
soundBA.position = 0;
trace("Start POS "+soundBA.position); //traces 0
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, sound_sampleDataHandler, false, 0, true);
ch=sound.play();
this.addEventListener(Event.ENTER_FRAME, updateSeek, false, 0, true);
public function updateSeek(event:Event):void {
trace("current Pos "+soundBA.position); //the first trace event is "current Pos 163840"
}
function sound_sampleDataHandler(event:SampleDataEvent):void {
for (var i:int = 0; i < 8192; i++)
{
if (soundBA.bytesAvailable < 4)
{
break;
}
var sample:Number = soundBA.readFloat();
event.data.writeFloat(sample);
event.data.writeFloat(sample);
}
}
This is because soundBA.position is position in byte array, not position of playback. It runs ahead of playback position because of sound lag. To determine current playback position use SoundChannel.position:
public function updateSeek(event:Event):void {
trace("current pos in ms: " + ch.position);
trace("current pos in bytes: " + (ch.position * 44.1 * 4 * 2));
trace("current pos in %: " + (100 * ch.position / sound.length));
}
UPD: I was referring to the case when sound is decoded using additional Sound object, e.g.:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
import flash.utils.ByteArray;
public class SoundTest extends Sprite
{
private var soundSrc:Sound;
private var soundPlayer:Sound;
private var soundData:ByteArray;
private var soundChannel:SoundChannel;
public function SoundTest()
{
soundSrc = new Sound();
soundSrc.addEventListener(Event.COMPLETE, startPlayback);
soundSrc.load(new URLRequest("sound.mp3"));
}
private function startPlayback(e:Event = null):void
{
soundData = new ByteArray();
soundSrc.extract(soundData, soundSrc.length * 44.1, 0);
soundData.position = 0;
soundPlayer = new Sound();
soundPlayer.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
soundChannel = soundPlayer.play();
addEventListener(Event.ENTER_FRAME, updateTime);
}
private function onSampleData(e:SampleDataEvent):void
{
for (var i:int = 0; i < 8192; i++)
{
if (soundData.bytesAvailable < 4)
{
break;
}
var sampleL:Number = soundData.readFloat();
var sampleR:Number = soundData.readFloat();
e.data.writeFloat(sampleL);
e.data.writeFloat(sampleR);
}
}
private function updateTime(e:Event):void
{
trace("current pos in ms: " + soundChannel.position);
trace("current pos in bytes: " + (soundChannel.position * 44.1 * 4 * 2));
trace("current pos in % (method 1): " + (100 * soundChannel.position / soundSrc.length));
// it also works
trace("current pos in % (method 2): " + (100 * soundChannel.position / (soundData.length / (44.1 * 4 * 2))));
}
}
}

Actionscript color picker

I am trying to create a Colorpicker control for my application. I prefer pure actionscript. Does someone know how to create a picker like this: http://parasolarchives.com/tools/colorpicker/
Most interestingly I am interested how to draw the gradient because the gradient has a saturation,
this is a picker i use myself, hope it'll be useful:
package lazylib.ui.generated
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.GradientType;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import lazylib.broadcast.evts.ColorEvent;
import lazylib.broadcast.Radio;
/**
* ...
* #author www0z0k
*/
public class Picker extends Sprite
{
private var bmpc: Bitmap;
private var bmp:BitmapData;
private var id:String;
private var w:int;
private var h:int;
public static const COLOR_PICKED_EVT_TYPE: String = 'picked by picker';
public function Picker(_id:String, _w:int = 256, _h:int = 256, _x:int = 0, _y:int = 0)
{
id = _id;
w = _w;
h = _h;
x = _x;
y = _y;
bmp = new BitmapData(w, h);
bmpc = new Bitmap(bmp);
addChild(bmpc);
refillBmp(0x7f7f7f);
}
public function get ID():String { return id; }
private function refillBmp(overColor:int = 0x7f7f7f, alphaStep:Number = 0.006):void {
var rtspr:Sprite = new Sprite();
var spr:Sprite = new Sprite();
var colors:Array = new Array(0xff0000,0xff7f00,0xffff00,0x7fff00,0x00ff00, 0x00ff7f, 0x00ffff,0x007fff,0x0000ff, 0x7f00ff,0xff00ff, 0xff007f, 0xff0000);
var alphas: Array = new Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
var ratios: Array = new Array(10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210, 230, 250);
var matrix:Matrix = new Matrix();
matrix.createGradientBox(w, h);
spr.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix);
spr.graphics.drawRect(0, 0, w, h);
spr.graphics.endFill();
rtspr.addChild(spr);
var spr2:Sprite = new Sprite();
rtspr.addChild(spr2);
var startA: Number = 1;
for (var i:int = 0; startA > 0; i++) {
startA -= alphaStep;//orig 0.004!!!
spr2.graphics.lineStyle(1, overColor, startA);
spr2.graphics.moveTo(0, h - i);
spr2.graphics.lineTo(w, h - i);
}
bmp.draw(rtspr, new Matrix());
graphics.beginFill(0, 0);
graphics.drawRect(0, 0, w, h);
graphics.endFill();
buttonMode = true;
addEventListener(MouseEvent.CLICK, onClick);
}
public function adjustDarkness(percent:int):void {
var colorValue: int = int(255 * percent / 100);
var currentGray:int = colorValue + colorValue << 8 + colorValue << 16;
refillBmp(colorValue);
}
private function onClick(e:MouseEvent):void {
var col: int = bmp.getPixel(e.localX, e.localY);
Radio.broadcast(new ColorEvent(COLOR_PICKED_EVT_TYPE + id, col));
dispatchEvent(new ColorEvent(COLOR_PICKED_EVT_TYPE + id, col));
}
}
}
Radio is a global dispatcher class (posted here if you need it), ColorEvent is just an event with an int color field, adjustDarkness is usually called from an external scrollbar. Let me know if a working example is needed.
I'm not sure this would be too accurate, but I think I can give you a few ideas:
You could grab that same squared image you are showing (or photoshop's for that matter) and change it's hue to get the whole color range.
If you want to draw it, mathematically I don't think it's too hard to do... for the cyan, for instance, the Y axis should control the maximum amount of color in all channels, and the X axis should control the proportion of red in the mix.