ActionScript 3 - adding gradient to object - actionscript-3

I have an instance of a MovieClip called 'BlueBox', which is just a 'Drawing Object' which is blue. It is inside a container called 'option1MC' which is inside 'option1Container' which is on the stage.. It's color can be changed like so:
option1Container.addEventListener(MouseEvent.MOUSE_OVER, option1ContainerOver);
var optionOver:ColorTransform = new ColorTransform();
optionOver.color = 0xC56516;
function option1ContainerOver(evt:Event):void {
option1Container.option1MC.BlueBox.transform.colorTransform = optionOver;
}
I want to change the color to a gradient. This is what I tried:
var mtr:Matrix = new Matrix();
mtr.createGradientBox(option1Container.option1MC.BlueBox.width, option1Container.option1MC.BlueBox.height, 0, 0, 0);
mtr.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x0000FF], [1, 1], [0x00, 0xFF], mtr);
mtr.graphics.drawRect(0,0,option1Container.option1MC.BlueBox.width, option1Container.option1MC.BlueBox.height);
However, right now when I run the .fla file, it i giving me an error saying:
Access of possible undefined property graphics through a reference with static type flasg.geom:Matrix:
and is referring to the lines
mtr.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x0000FF], [1, 1], [0x00, 0xFF], mtr);
mtr.graphics.drawRect(0,0,option1Container.option1MC.BlueBox.width, option1Container.option1MC.BlueBox.height);
Any idea why?

A Matrix does not have a graphics property. You would need to apply this to a DisplayObject with a graphics property. That would look something like this with your setup:
//create the sprite to do the gradient fill on or use your MovieClip
//var spriteObject:Sprite = new Sprite() or just use option1Container;
//enter your matrix
var mtr:Matrix = new Matrix();
mtr.createGradientBox(option1Container.BlueBox.width, option1Container.BlueBox.height, 0, 0, 0);
//apply it to the sprite
sprite.graphics.beginGradientFill("linear", [0xFF0000, 0x0000FF], [1, 1], [0x00, 0xFF], mtr);
sprite.graphics.drawRect(0, 0, 50, 40);
sprite.graphics.endFill();
addChild(sprite);
I created a sprite variable here, which is not necessary as you can just swap sprite with option1Container
You can reference adobe's help for this as well: http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7dd7.html
Now if you drew the MovieClip graphics in the IDE you won't currently be able to change it. In which case you can create a new MovieClip and add it to your container like so:
//note I made a target variable just to save on typing:
var target:MovieClip = option1Container.option1MC.BlueBox;
var gradientLayer:MovieClip = new MovieClip();
var gradientBox:Matrix = new Matrix();
gradientBox.createGradientBox(target.width, target.height, 0, 0, 0);
gradientLayer.graphics.beginGradientFill("linear", [0xFF0000, 0x0000FF], [1, 1], [0x00, 0xFF], gradientBox);
gradientLayer.graphics.drawRect(0, 0, target.width, target.height);
gradientLayer.graphics.endFill();
//giving the asset a name will allow you to easily remove it later
gradientLayer.name = "gradientLayer";
target.addChild(gradientLayer);
Notice I gave the gradient asset a name of "gradientLayer". If you want to remove this child later on you can do that with:
option1Container.option1MC.BlueBox.removeChild( option1Container.option1MC.BlueBox.getChildByName( "gradientLayer" ) );

Related

Dynamically generated display object as a gradient mask

I just want to create a gradient mask –which is generated dynamically through AS3 code– for an object (a pentagon in my following example,) and I simply, cannot! [The SWF file of what I've tried.]
The code works just fine unless it ignores the alpha gradient of the dynamically created Sprite for being used as a gradient mask (it's being treated as a solid mask), while the exact code acknowledges the "on-stage" created object (through the user interface) for being a gradient mask!
I think the runtime just cannot cache the object as bitmap and hence the ignorance! However, I'm stuck at making that happen! So please, shed some lights on this, any help is greatly appreciated in advance :)
var X:Number = 100, Y:Number = 35, W:Number = 350, H:Number = 150;
var mat:Matrix = new Matrix();
mat.createGradientBox(W, H, 0, X, Y);
var gradientMask:Sprite = new Sprite();
gradientMask.graphics.beginGradientFill(GradientType.LINEAR, [0, 0], [1, 0], [0, 255], mat);
gradientMask.graphics.drawRect(X, Y, W, H);
gradientMask.graphics.endFill();
pentagon1.cacheAsBitmap = true;
pentagon2.cacheAsBitmap = true;
onStageGradient.cacheAsBitmap = true;
gradientMask.cacheAsBitmap = true;
pentagon1.mask = gradientMask;
pentagon2.mask = onStageGradient;
stage.addEventListener(Event.ENTER_FRAME, _onEnterFrame);
function _onEnterFrame(e:Event):void {
pentagon1.x += 7;
pentagon2.x += 7;
if (pentagon1.x > 500) {
pentagon1.x = 0;
pentagon2.x = 0;
}
}
You have to add the gradientMask to the display list to have it in effect.
pentagon1.parent.addChild(gradientMask);

Rectangle with rounded corners and gradient fill

I'm trying to make a rectangle with rounded corners and a gradient. I have this code:
import flash.geom.*;
var rect:Shape = new Shape();
rect.graphics.lineStyle(5, 0x00ff00, 0); //(thickness, color, alpha)
var fillType:String = "linear";
var colors:Array = [0x000000, 0xFFFF00,0xFFFFFF];
var alphas:Array=[1,1,1];
var ratios:Array=[0,127,255];
var matrix:Matrix = new Matrix();
matrix.createGradientBox(20, 20, 0, 0, 0);
rect.beginGradientFill(fillType, colors, alphas, ratios, matrix) : Void;
rect.graphics.drawRoundRect(720,450, 213.4, 29.1, 12, 12);
rect.graphics.endFill();
addChild(rect);
I'm getting an error from this line :
rect.beginGradientFill(fillType, colors, alphas, ratios, matrix) : Void;
1078: Label must be simple identifier.
I'm a novice and everything I look up seems to have a bunch of terminology I don't quite understand, so please keep it simple.
I want the yellow (FFFF00) to actually be a color picked from the stage so if that can be thrown in there easily without complicating the answer to the above question, feel free.
In your code you have two errors in the same line :
rect.beginGradientFill(fillType, colors, alphas, ratios, matrix) : Void;
We use void ( with lower v, it's not Void ) to indicate the type of a function which will return nothing when we are defining it, not when calling that function.
Then beginGradientFill() is a function of the Graphics class so it should be used with rect.graphics :
rect.graphics.beginGradientFill(fillType, colors, alphas, ratios, matrix);
Then your code can be like this (it's an example) :
var fillType:String = "linear";
var colors:Array = [0x000000, 0xFFFF00, 0xFF0000];
var alphas:Array=[1, 1, 1];
var ratios:Array=[0, 127, 255];
var matrix:Matrix = new Matrix();
matrix.createGradientBox(200, 10, 0, 0, 0);
var rect:Shape = new Shape();
rect.graphics.lineStyle(5, 0x00ff00, 0);
rect.graphics.beginGradientFill(fillType, colors, alphas, ratios, matrix)
rect.graphics.drawRoundRect(0, 0, 200, 200, 12, 12);
rect.graphics.endFill();
addChild(rect);
For more about gradient, take a look on Graphics.beginGradientFill(), and on creating gradient lines and fills ...
Hope that can help.
preface: didn't see the comment from before, but that's the correct solution.
The breakpoint is here:
rect.beginGradientFill(fillType, colors, alphas, ratios, matrix) : Void;
The function call should not have the " : Void" identifier. That's used when the function is originally written.
try this:
rect.beginGradientFill(fillType, colors, alphas, ratios, matrix);

Render to texture not functioning

I'm trying to test Stage3D's setRenderToTexture function, but my test code is not providing any output. I was hoping someone could tell me why - I've tried practically everything to get this working. The code I've created is below:
import flash.events.Event;
import flash.display.*;
import flash.display3D.*;
import flash.display3D.textures.Texture;
import AGALMiniAssembler;
//using stage size in several locations for simplicity - needs to be square, 2^n
[SWF(width='512', height='512', backgroundColor='0x000000', frameRate='60')]
//vars
var context0:Context3D;
var vBuff:VertexBuffer3D;
var iBuff:IndexBuffer3D;
var tex0:Texture;
var tex1:Texture;
var vShader:AGALMiniAssembler = new AGALMiniAssembler();
var fShader:AGALMiniAssembler = new AGALMiniAssembler();
var program:Program3D;
//create a square
var square:Shape = new Shape();
square.graphics.beginFill(0xaa00ff,1);
square.graphics.drawRect(10, 10, stage.stageWidth - 20, stage.stageHeight - 20);
//draw square to bitmapdata and create one blank bitmapdata
var tex0data:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false,0);
tex0data.draw(square);
var tex1data:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false,0);
//initialize stage3d
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, initStage3D);
stage.stage3Ds[0].requestContext3D();
function initStage3D(e:Event):void {
context0 = stage.stage3Ds[0].context3D;
context0.configureBackBuffer(stage.stageWidth, stage.stageHeight, 0);
//create buffers - simple quad
var vBuff_vec:Vector.<Number> = new <Number>[-1, -1, 0, 0, 1,
-1, 1, 0, 0, 0,
1, 1, 0, 1, 0,
1, -1, 0, 1, 1];
var iBuff_vec:Vector.<uint> = new <uint>[0, 1, 2, 0, 2, 3]
vBuff = context0.createVertexBuffer(4, 5);
vBuff.uploadFromVector(vBuff_vec, 0, 4);
iBuff = context0.createIndexBuffer(6);
iBuff.uploadFromVector(iBuff_vec, 0, 6);
//load bitmapdata into textures - square to tex0 and blank to tex1
tex0 = context0.createTexture(tex0data.width,tex0data.height,'bgra',false);
tex0.uploadFromBitmapData(tex0data);
tex1 = context0.createTexture(tex1data.width, tex1data.height,'bgra',true);
tex1.uploadFromBitmapData(tex1data);
//create and upload simple shader program
vShader.assemble('vertex', 'mov v0, va1 \n'+ //uv coords to v0
'mov op, va0'); //output xyz coords
fShader.assemble('fragment', 'tex oc, v0, fs0 <2d, linear, nomip>'); //output texture at fs0
program = context0.createProgram();
program.upload(vShader.agalcode, fShader.agalcode);
context0.setProgram(program);
//set buffers
context0.setVertexBufferAt(0, vBuff, 0, 'float3');
context0.setVertexBufferAt(1, vBuff, 3, 'float2');
//prep rendering
addEventListener(Event.ENTER_FRAME, render);
}
function render(e:Event):void {
context0.clear();
//render tex0 onto tex1
context0.setRenderToTexture(tex1);
context0.setTextureAt(0, tex0);
context0.drawTriangles(iBuff);
//render tex1 to back buffer and present
context0.setTextureAt(0, tex1);
context0.setRenderToBackBuffer();
context0.drawTriangles(iBuff);
context0.present();
}
EDIT: I have noticed that changing the color of the blank bitmap does change the color of the final output - it's being displayed, but the square isn't being rendered to it.
FINALLY figured this out! There is a subtle, but important, step that must be taken before a texture is viable as a render target - it must be cleared after the render target is switched. Revising the render function as follows causes the program to function as expected:
function render(e:Event):void {
//render tex0 onto tex1
context0.setRenderToTexture(tex1);
context0.clear();
context0.setTextureAt(0, tex0);
context0.drawTriangles(iBuff);
//render tex1 to back buffer and present
context0.setTextureAt(0, tex1);
context0.setRenderToBackBuffer();
context0.clear();
context0.drawTriangles(iBuff);
context0.present();
}

How to attach a moiveClip into as3isolib grid?

I am a beginner with using AS3 and as3isolib. I am trying to add some MC from the fla library into an isoGrid object. I tried to use addChild() method of the IsoGrid class but it gave me an error saying: 1067: Implicit coercion of a value of type [MovieClip Name] to an unrelated type as3isolib.data:INode. Which I think wants me to use the node class.
Any idea how to do such a thing?
Thank you in advance.
as3isolib use it's own display list like rendering tree, add all nodes in this tree must implements as3isolib.data:INode. There are two possibility to add flash native display objects to the IsoScene:
Take a look on this small tutorial:
//create IsoView, IsoScene and IsoGrid - default from as3isolib
var view:IsoView = new IsoView();
view.setSize(stage.stageWidth, stage.stageHeight);
addChild(view);
var scene:IsoScene = new IsoScene();
view.addScene(scene);
var grid:IsoGrid = new IsoGrid({cellSize:32});
grid.setGridSize(800, 600);
grid.stroke = new Stroke(0, 0x576F33);
grid.render();
//create iso box, just for demo
var obj:IsoBox = new IsoBox();
obj.setSize(32, 32, 64);
obj.moveTo(5*32, 5*32, 1);
//first possiblity to add flash.display.Shape to the iso scene - using IsoSprite.sprites
var isoSprite:IsoSprite = new IsoSprite();
isoSprite.moveTo(5*32, 7*32, 1);
var shape1:Shape = new Shape();
shape1.graphics.beginFill(0xFF0000, 1);
shape1.graphics.drawRect(0, 0, 32, 32);
isoSprite.sprites = [shape1];
//second possiblity to add flash.display.Shape to the iso scene - using IsoDisplayObject.container
var isoObj:IsoDisplayObject = new IsoDisplayObject();
isoObj.moveTo(7*32, 7*32, 1);
var shape2:Shape = new Shape();
shape2.graphics.beginFill(0x0000FF, 1);
shape2.graphics.drawRect(0, 0, 32, 32);
isoObj.container.addChild(shape2);
//add all objects to the scene and render all
scene.addChild(grid);
scene.addChild(obj);
scene.addChild(isoSprite);
scene.addChild(isoObj);
scene.render();

Draw shadow without filter on Graphics object

I have a complex graphics data on a sprite or a shape (no matter which is exactly).
But I want to draw shadow (inner too) for one Rect ( [10, 10, 240, 25] for example) or another path.
/// code before
grObj.graphics.drawRect( 10, 10, 240, 25);
/// -> draw inner shadow on this objcect somehow
/// code after
Is it possible to perform w\o filters?
ps. http://ipicture.ru/uploads/100927/RHZF1K6Exu.png
solving:
BitmapData(*).applyFilter( *,*,*,*); // play with this function :)
also http://help.adobe.com/ru_RU/AS3LCR/Flash_10.0/flash/display/BitmapData.html#applyFilter()
i'm assuming you don't want to add filters to your object because you plan on adding a colorTransform and do not want the filters to also change color.
if that's the case what you can do is separate the filter by creating another sprite of the same size as the original, add a drop shadow filter to the new sprite with the hideObject parameter set to true.
//display object
var grObj:Sprite = new Sprite();
grObj.graphics.beginFill(0xFF0000, 1);
grObj.graphics.drawRect(0, 0, 240, 25);
grObj.graphics.endFill();
//filter object
var dsFilter:Sprite = new Sprite();
dsFilter.graphics.beginFill(0);
dsFilter.graphics.drawRect(0, 0, grObj.width, grObj.height);
dsFilter.graphics.endFill();
dsFilter.filters = [new DropShadowFilter(4.0, 45, 0, 1.0, 4.0, 4.0, 1.0, 3, true, false, true)];
//display list
grObj.x = dsFilter.x = 10;
grObj.y = dsFilter.y = 10;
addChild(grObj);
addChild(dsFilter);