Monday, 31 May 2010

TextLineMetrics...continued

This code works:

test_txt.addEventListener(Event.CHANGE,getLonger);
function getLonger(evnt:Event):void {
var met:TextLineMetrics = test_txt.getLineMetrics(0);
trace(met.height);
trace(met.ascent);
trace(met.descent);
trace(met.leading);
trace(' ');
if(test_txt.textHeight > test_txt.height){
test_txt.height = test_txt.textHeight + 6;
}
}

So, why would 6 be the magic number? I tried this in font size 18, 24, and 96, and different font faces as well. (By the way, in my previous efforts, the first line wasn't scrolling up because of using '+=', actually, it was because there wasn't enough added. So this can happen with '=' as well, if the textfield height isn't large enough.)

Anyway, if you have a look at this diagram:


(from http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/text/TextLineMetrics.html)

You can see a '2-pixel gutter' at the top and bottom of the text field, that gives 4 extra pixels, and there is the 'leading' value as well. I have traced out the 'leading' value in different faces and sizes, it is always 2.

So my theory is, that you need to take account of the gutters, and the leading for the next line. So for safety's sake, I will use '4 + met.leading';

UPDATE: You can set 'leading' in the properties panel, if you mouse over the second option in 'Spacing', it says 'Line spacing' - Mine was set to 2.0, but if I change it to, for example 5, the met.leading traces out 5.

Sunday, 30 May 2010

TextLineMetrics...to be continued.

OK, I am currently trying to make a text box that grows in length when the typer makes extra lines.
I tried:

if(test_txt.textHeight > test_txt.height) {
test_txt.height = (test_txt.height /(test_txt.numLines - 1)) * test_txt.numLines;
}

but text fields have some extras around the edges and stuff, so the text box got too big as time went by.

As a sidenote, I would like to mention that, if you use += and just try to add to the textfield height instead of changing the textfield height, that the first line scrolls up the text box.

Thursday, 27 May 2010

stageHeight after resize cont.

OK, it does pick it up, but technically, the stageHeight hasn't changed until the function has completed, so asking a movieClip to do something based on the new stageHeight when it hasn't actually changed yet is kind of silly...

stage.stageHeight after JavaScript's resize

I am trying to use the resize in an animation now, and I wanted the copyright movie clip to reposition itself when the movie got bigger. I got it to keep track of how far away it was from the bottom of the screen, but it didn't move, so I think perhaps that flash doesn't realise when it's stageHeight changes, but I will check on that now...

HTML Notation Converter

Right, two text boxes on stage, one input:

htmlinput.text = '';
htmlinput.addEventListener(Event.CHANGE,outputhtml);
var htmlCode:Array = ['<','>',"\r",'&','"'];
var htmlNotation:Array = ['&lt;','&gt;',"\n",'&amp;','&quot;'];
function outputhtml(evnt:Event):void {
htmloutput.text = "<pre>";
var str:String = htmlinput.text;
for(var i:uint = 0; i<str.length; i++) {
var char:String = str.charAt(i);
trace(char+' '+str.charCodeAt(i));
var ind:int = htmlCode.indexOf(char);
if(ind == -1) {
htmloutput.appendText(char);
}else{
htmloutput.appendText(htmlNotation[ind]);
}
}
htmloutput.appendText("</pre>");
}


This code was also output using it, and I put the ampersand and quote marks in, because it was great at converting html into html notation, but my actual html notation was getting converted back to html by the blog editor!

It doesn't recognise all linebreaks, but it will pick up on the proper ones, web text is a bit funny like that...

HTML notation conversion

OK... I have checked it and it works.

Apparently you have to surround the whole thing with
<pre>...</pre>
tags to let the editor or whatever know that it is fake html, and you still have to use the notation.

Can you imagine how long it would take me to do that by hand?!? And I'd probably make some mistakes.

So my next task is to make a simple swf to convert my html into html notation, because it really is so handy to have code on this blog, it is so easy for me to find when I need it.
Update:
Here it is...

HTML code in posts

I have a link that puts together all the notation I will probably need to put html on the posts without the editor getting confused.

http://www.blogspottutorial.com/2008/12/html-code-appears-in-posting.html

Wednesday, 26 May 2010

Resize in IE

I don't know what the problem was, maybe it was something in the html code... I was using code I got from Flash 8 output.

Anyway...

This is the html (I had to alter the html to get past the blog editor), it works for both IE and FF:

<body>
<script type="text/javascript">
function resize(wid,heig) {
var infoTag = document.getElementById("info");
var objectTag = document.getElementById("divtest");
var embedTag = document.getElementById("embedTag");
infoTag.innerHTML = wid;
objectTag.setAttribute("width",wid);
objectTag.setAttribute("height",heig);
embedTag.setAttribute("width",wid);
embedTag.setAttribute("height",heig);
}
</script>
<div id='info'></div>
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="500" height="500" id="divtest" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="sameDomain" />
<param name="movie" value="divtest.swf" />
<param name="quality" value="high" />
<param name="scale" value="noscale" />
<param name="salign" value="lt" />
<param name="bgcolor" value="#ffffff" />
<embed id="embedTag" src="divtest.swf" loop="false" menu="false" quality="high" scale="noscale" bgcolor="#ffffff" width="500" height="500" name="divtest" align="middle" salign="lt" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer" />
</object>
</body>


It resizes the area for the swf, and it also outputs the width of the file on top of the swf - just so I can remember how to use the div tag later.

The actionscript is really quite simple:

btn.addEventListener(MouseEvent.CLICK,callIt);
function callIt(evnt:MouseEvent) {
bg.width += 20;
bg.height += 20;
ExternalInterface.call('resize',bg.width,bg.height);
}

And voila!

Task Manager

How to run the task manager from the command line, i.e. if you are working remotely and a program crashes, as I am and it has:

Click Start.
Click Run.
Type 'taskmgr.exe' into the text box.
Click OK.

Calling alerts with ExternalInterface

My ominous prediction came true - Internet Explorer is refusing to cooperate.

On the plus side, I found out that you can do Javascript alerts without defining any functions on your html page.

I attached this code to a button:

ExternalInterface.call('alert','Work darnit!');

and it actually worked (on both IE and Firefox). Which was nice.

Which means that the External Interface call does work on IE, but I don't know why the whole thing is not working.

Resizing the Stage

This code was pretty hard to get hold of on the internet, actually I couldn't find it. Anyone who came close to answering kind of seemed to assume that you knew what a 'DIV' tag was for and how to use it. Well, I didn't, and I didn't, but now I kind of do!

The problem is this, I will be making a swf whose length will change, depending on what the user writes, and it will certainly be longer than the screen. I don't want to make a really long swf, that people can scroll down even though there is nothing there, on the off chance that someone might enter enough text for it to need to be that long, and what if they write even more!

Also, most of the things that were addressing this, were trying to resize the stage, so it could fit in the browser window, and again, not my problem. Anyway, the code that they gave out was really complex, and I don't like to use code unless I understand what it actually means...

So, first things first, the 'DIV' tag.
Apparently, you can put this tag around things, give it an id attribute, and then refer to it with JavaScript. But, you can do this with ordinary tags anyway, so why bother (unless you have more than one swf on the page).

It works like this:
<embed id="embedtag" src=...


and then in your javascript function:
var swfTag = document.getElementById('embedtag');

Then you can alter its attributes:
swfTag.setAttribute('height','600');


The stage of the swf will automatically update, it doesn't refresh the movie or anything.

Then I had a bit of a problem with how the swf would be displayed on the new stage. It wouldn't be aligned to the side. Now I checked, and the movie clip that was on 0, still thought it was on 0, so it wasn't moving. I fixed this by adding an attribute to the embed tag -salign="lt"-aligning it's side to the left. I wasn't using the code output by the CS3 flash publisher, because it spits out so much javascript, I can't make sense of it, or how to alter it.

I put a button in my flash movie that increased the size of one of the movie clips on screen, and then used ExternalInterface to nake sure that the stage size on the html side of things was big enough, and with the salign="lt" bit, it worked.

I haven't tried it with the ie tag yet, what are the chances that I will come across some unexpected problems...quite high, I'd say.

Flash + JavaScript: How to Use External Interface

First a short reminder on External Interface:

I use it to get info or do things that JavaScript has access to, and that I don't, for example, doing alerts. You can pass it parameters and get data from it.

There may be issues with testing it locally though.

Example:

var val:Number = ExternalInterface.call('funcName','parameter1','parameter2');

The first parameter is the name of the javascript function on the html page, the others are parameters to be passed to the function.

On your html page, you would have something like:

<script type="text/javascript">
function funcName(text1,text2){ 
return text2;
}
</script>


Of course, that would be completely useless, but I don't deal with JavaScript much, and that is what I could come up with off the top of my head. Pathetic, huh?

Anyway...

Thursday, 20 May 2010

How to get the width or height of a masked movie clip in Flash

This obviously goes for height as well...

If you have a masked movie clip and you access its height with as3, the result includes the size of the whole thing, not just the bit that is visible due to the mask, to get around this, name the movie clip that is masking it, and access the width/height of that instead.

Tuesday, 18 May 2010

Video player working!

Right, as far as I can tell, my video player is working, so here is the code, so that I don't have to go hunting for it next time:

this.alpha = 0;
this.visible = false;
var skrBound:Rectangle = new Rectangle(skrbr.x,skr.y,skrbr.width,0);
function comeIn(vid:String) {
this.visible = true;
this.addEventListener(Event.ENTER_FRAME,fadeIn);
MovieClip(root).offFunction(this,Event.ENTER_FRAME,fadeIn);
MovieClip(this.parent).vidholder_mc.removeEventListener(Event.ENTER_FRAME,MovieClip(this.parent).vidholder_mc.rotateIt);
MovieClip(root).unoffFunction(MovieClip(this.parent).vidholder_mc,Event.ENTER_FRAME,MovieClip(this.parent).vidholder_mc.rotateIt);
trace(vid);
vempty.loadVideo(vid);
}
function fadeIn(evnt:Event):void {
this.alpha += (1-this.alpha)/MovieClip(root).easeVal;
if(this.alpha > 0.9) {
this.alpha = 1;
this.removeEventListener(Event.ENTER_FRAME,fadeIn);
MovieClip(root).unoffFunction(this,Event.ENTER_FRAME,fadeIn);
vempty.playVideo(null);
skr.addEventListener(Event.ENTER_FRAME,positionSeeker);
MovieClip(root).offFunction(skr,Event.ENTER_FRAME,positionSeeker);
}
}
function comeOut(evnt:MouseEvent) {
vempty.stopVideo(null);
this.addEventListener(Event.ENTER_FRAME,fadeOut);
MovieClip(root).offFunction(this,Event.ENTER_FRAME,fadeOut);
}
function fadeOut(evnt:Event):void {
this.alpha -= this.alpha/MovieClip(root).easeVal;
if(this.alpha < 0.1) {
this.alpha = 0;
this.visible = false;
MovieClip(this.parent).vidholder_mc.addEventListener(Event.ENTER_FRAME,MovieClip(this.parent).vidholder_mc.rotateIt);
MovieClip(root).offFunction(MovieClip(this.parent).vidholder_mc,Event.ENTER_FRAME,MovieClip(this.parent).vidholder_mc.rotateIt);
this.removeEventListener(Event.ENTER_FRAME,fadeOut);
MovieClip(root).unoffFunction(this,Event.ENTER_FRAME,fadeOut);
}
}
function setUpBtns() {
play_btn.addEventListener(MouseEvent.CLICK,vempty.playVideo);
play_btn.addEventListener(MouseEvent.ROLL_OVER,MovieClip(root).buttonReactionOn);
pause_btn.addEventListener(MouseEvent.CLICK,vempty.pauseVideo);
pause_btn.addEventListener(MouseEvent.ROLL_OVER,MovieClip(root).buttonReactionOn);
skip_btn.addEventListener(MouseEvent.CLICK,vempty.skipVideo);
skip_btn.addEventListener(MouseEvent.ROLL_OVER,MovieClip(root).buttonReactionOn);
close_btn.addEventListener(MouseEvent.CLICK,comeOut);
close_btn.addEventListener(MouseEvent.ROLL_OVER,MovieClip(root).buttonReactionOn);
skr.addEventListener(MouseEvent.MOUSE_DOWN,skVideo);
skr.addEventListener(MouseEvent.ROLL_OVER,MovieClip(root).buttonReactionOn);
skrbr.addEventListener(MouseEvent.ROLL_OVER,MovieClip(root).buttonReactionOn);
skrbr.addEventListener(MouseEvent.CLICK,skPositionVideo);
}
setUpBtns();
function positionSeeker(evnt:Event):void {
skr.x = skrbr.x + (vempty.giveProportion()*skrbr.width);
}
function skVideo(evnt:MouseEvent):void {
skr.removeEventListener(Event.ENTER_FRAME,positionSeeker);
MovieClip(root).unoffFunction(skr,Event.ENTER_FRAME,positionSeeker);
vempty.pauseVideo(null);
skr.startDrag(true,skrBound);
skr.addEventListener(Event.ENTER_FRAME,positionVideo);
MovieClip(root).offFunction(skr,Event.ENTER_FRAME,positionVideo);
stage.addEventListener(MouseEvent.MOUSE_UP,finPosition);
}
function positionVideo(evnt:Event):void {
var pos:Number = (skr.x - skrbr.x)/skrbr.width;
vempty.gotoPosition(pos);
}
function finPosition(evnt:MouseEvent):void {
stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_UP,finPosition);
skr.removeEventListener(Event.ENTER_FRAME,positionVideo);
MovieClip(root).unoffFunction(skr,Event.ENTER_FRAME,positionVideo);
skr.addEventListener(Event.ENTER_FRAME,positionSeeker);
MovieClip(root).offFunction(skr,Event.ENTER_FRAME,positionSeeker);
vempty.playVideo(null);
}
function skPositionVideo(evnt:MouseEvent):void {
var pos:Number = ((this.mouseX - skrbr.x)/skrbr.width);
vempty.gotoPosition(pos);
}

That is the code that sits in the movie clip with all the buttons. The empty movie clip ('vempty') on stage has the code inside that handles the netstream etc:

var connection:NetConnection = new NetConnection();
var stream:NetStream;
var video:Video = new Video(MovieClip(this.parent).igs.width,MovieClip(this.parent).igs.height);
var metaObj:Object = new Object();
var duratn:Number;
function onMetaData(obj:Object):void {
duratn = obj.duration;
}

connection.connect(null);
stream = new NetStream(connection);
stream.client = metaObj;
metaObj.onMetaData = onMetaData;
video.attachNetStream(stream);
addChild(video);

stream.addEventListener(NetStatusEvent.NET_STATUS,comped);
function comped(evnt:NetStatusEvent) {
if(String(evnt.info.code) == "NetStream.Play.Stop"){
stream.seek(0);
stream.pause();
takedownVideo();
}
}
function loadVideo(vid:String):void {
stream.play(vid);
stream.seek(0);
stream.pause();
}
function pauseVideo(evnt:MouseEvent) {
stream.pause();
takedownVideo();
}
function playVideo(evnt:MouseEvent) {
stream.resume();
holdupVideo();
}
function skipVideo(evnt:MouseEvent) {
stream.seek(0);
stream.resume();
holdupVideo();
}
function holdupVideo() {
MovieClip(root).logobg.addEventListener(MouseEvent.CLICK,stopVideo);
}
function takedownVideo() {
MovieClip(root).logobg.removeEventListener(MouseEvent.CLICK,stopVideo);
}
function stopVideo(evnt:MouseEvent) {
stream.pause();
}
function giveProportion():Number {
return stream.time/duratn;
}
function gotoPosition(pos:Number):void {
stream.seek(pos*duratn);
}

And thanks to http://flashenabledblog.com/2007/06/12/as3-mouse-events-and-mouse-related-user-actions/ and the commenters for showing how to imitate an 'onReleaseOutside' event, by temporarily adding a MOUSEUP event listener to the stage.

Very handy...

Sunday, 16 May 2010

NetStream problem

Right, I just had one of those 'what the...!?!' moments, where something works, and then you make some entirely unrelated changes, and then it all falls apart, for no apparent reason.

These things normally drive me to distraction, and I just delete it and try a workaround. But today, there was no workaround, and I learnt an important lesson.

The error that I was getting was one of these:

TypeError: Error #1010: A term is undefined and has no properties.

I hate these errors, because they never tell you the name of the term that they did not recognise, is that so hard? Anyway, under the error phrase, there is usually, to the best of my recollection, a list of functions. The lowest one down is the first one to be called, the next one is one that called by the one beneath it, and so on, until you get to the one at the top, which is the one that contained an unrecognised term.

The quickest way to figure out exactly which one it is, is to comment out all the actual code, and get flash to trace out each variable that the function is supposed to use. For me this worked, because something came out null, when it should have been a NetStream object.

Here is the thing that really confused me, the 'stream' variable was clearly declared at the beginning of the script, and as I said the whole thing was working just a few changes ago.

The next step I took was to trace out a message saying what stream was several times in the script, and it only traced out the first one! The problem was not in the function that had the unrecognised term (stream), actually, it was at the top of the script, and it had nothing to do with 'stream'. I had a line of code referring to a movie clip that I had just deleted, and it's absence was preventing the rest of the script from running properly. I should have picked up the error, but old trace statements meant that I didn't see the relevant error.

I'm glad I figured this one out - its so frustrating when you can't.

Tuesday, 11 May 2010

Ohh, forget it, I'll just fade it in.

The Latest Mystery

I am redoing something I did a few months ago, with a view to making the code better, and easier to manipulate.

Here's the thing, I've already done all of these techniques, and yet I am still coming across things that did not happen to me the first time around!

I have a movie clip with a z value, for some reason I don't understand, when I move my mouse, the event listeners on the movie clips 'under'/'behind' it, stop. Why?

Perhaps it is something to do with the perspective thing, but that didn't interfere with my Event.ENTER_FRAME events before?

Monday, 10 May 2010

I got that thing to work at last! It might not sound like it bu I love flash, and I think I do actually really like actionscript 3, I am able to do so much more with it than I was with as2, but it is so frustrating when things don't work because it has little quirks, which when you don't know what they are, can really waste a lot of your time.
Absolutely unbelievable!

I read on a few other websites that Flash doesn't like it if you pass it a query string with a leading '&', well apparently, it doesn't like them at the end either.

Getting data from MySQL

Today, I have been mostly... not getting data from a MySQL database.

I thought I had this sorted already - I had a script that could send data to a php script, then receive a query string and format the data as a URL variable.

As usual, when you try to actually use it for something - it turns out to be more complicated.

First of all, using capital letters in the query string that PHP is outputting is apparently not a good idea! Can you imagine?!? It took me three hours just to pin the problem down to that!

So then I though I had the problem sorted, but no.

I think it might be something to do with the length of the query string...

More on this later?