vrijdag 2 mei 2014

Error Handling for minified javascripts.

Why we minify

Javascript is often minified for production. This is also called 'uglification' sometimes. It means your javascript  is written like one long line.

What is the problem?

Minification can sometimes cause errors. It's hard to see if you made an error, or the minifier.
Sometimes an error just happens. We're not perfect.
In a minified file you'd get an error in your console like:
 Uncaught ReferenceError: faultyReference is not defined script.js: 2
When line 2 is 4000 characters long, it's a little heavy. Especially since most minifyers will also minify the variable faultyReference to something like: a132.


New standard fixes the problem

In the new standard for the window.onError event you don't just get a line, but also a column.
You can generate an error message for yourself:
 Uncaught ReferenceError: faultyReference is not defined script.js: line 2, col 3704
Now you know exactly where to debug...

Tell me how

Ok!
  1. start of 2014 this was working in Chrome. I don't know about other browsers, but if all else fails, develop in Chrome (I think it's the best development browser anyway) 
  2. before you execute any other script add something this:
 window.onerror=globalErrorListener;  
 function globalErrorListener(msg, url, line, col, obj)   
 {  
      console.log('--' + msg + ' ' + url + ': line ' + line  
      + ', col ' + col);  
 }  

Now in your console, you'll find the exact column where the error occured.
The obj is the stack, you can also log that, just add it to the string.

Tadaaa! And thank you chrome for implementing so fast. Hope this helps someone, it sure helped me!
more about this

vrijdag 18 april 2014

Vaarwel Adobe, vaarwel Creative Cloud

Gedurende de afgelopen 6 jaar heb ik veel geprutteld over Adobe.
Toch ben ik in het rijke 'bezit' van een licentie van de volledige Creative Cloud.
Nu heb ik besloten dit te gaan afbouwen.

Sinds Adobe Flash van Macromedia kocht is er veel veranderd in de wereld, maar ook in Flash zelf. Niet altijd ten goede. Veel updates met interface en workflow 'verbeteringen'.
As3 was een goede verbetering, maar nu backwards compatibility is opgegeven ben ik feitelijk alles 'kwijt' wat ik voor die tijd heb gedaan. Je kunt niet meer compileren. Dus heb ik gauw mijn oude licentie van flash5.5 weer geïnstalleerd. Ik kan nu weer dingen compileren om wijzigingen te maken.

Ik kan oude projecten converteren naar as3, maar als je dan toch bezig ben, waarom dan niet naar HTML5 en javascript? Da's tenminste open source en er wordt niet zomaar besloten om het niet meer te ondersteunen.
Ik werd het continue inloggen bij Creative Cloud wel erg zat en nu is als klap op de vuurpijl Flash opeens niet meer correct geïnstalleerd. Herinstalleren met Creative Cloud is een crime herinner ik me nog van de vorige keer dat dit gebeurde. Da's 2 x in 4 maanden.

Ik ben (al weer een paar maanden) bezig met het bouwen van een eigen games-platform in HTML5 en ik zeg: het is goed te doen. Er is veel documentatie en met het gebruik van een library als JQuery en goede programmeerkennis, wordt het zelfs gewoon een kwestie van even doorzetten.
Ik gebruikte nog wel Photoshop om assets te maken voor mijn game games en ook Flash voor animaties.
Nu ben ik mijn gewoontes aan het veranderen.
Ik ben aan het afbouwen. Hoe doe ik dat?

Ik ga langzaam over naar GRATIS, open source software.
-Notepad (geleverd bij windows) geeft je alle programmeer mogelijkheden.
-Chrome (en vrijwel iedere browser) heeft ingebouwde debug-mogelijkheden voor javascript
-Plaatjes maak je met GIMP (gratis Open source Photoshop variant, zonder hele fancy features, maar degelijk.).
-Vector tekeningen met Inkscape (SVG gebaseerd, maar erg flexibel)
-Animatie: http://www.pencil-animation.org/
-Muziek en geluid.. Adobe heeft geen muziek of geluidsprogramma, dus dat heeft niet specifiek te maken met Adobe. Ik heb/had Sony Soundforge, maar Audacity kan bijna alles wat soundforge kan..) Muziek maak ik met het gratis Anvil Studio.
-Video heb ik nog niet besloten, maar ik merk dat ik het meest werk met Flash 5,5 (creative cloud heeft op het moment even een probleem met FlashCS6, deze wil NIET openen.)
Voor alle andere dingen kijk ik naar deze lijst onder het kopje freeware: http://en.wikipedia.org/wiki/List_of_video_editing_software

Da's zo'n beetje alles wat ik doe.
Tja, dan rijst wel de vraag.. Waar heb ik Adobe nog voor nodig?
Continuïteit krijg ik waarschijnlijk eerder in  open-source projecten en deze hebben de neiging om algemeen geaccepteerde formaten te gebruiken. Dus zelfs als ze ermee stoppen, heb ik meer kans mijn video, game of plaatje of geluid later nog te kunnen openen en bewerken.

Maar je kunt toch licenties kopen.. Nee. Adobe heeft besloten alleen nog gas te geven op de 'creative cloud' en niet meer op de 'creative suite' (licenties van 'gewone' software)

Dus, goed voornemen: Vanaf nu alleen open source software, zo min mogelijk corporate afhankelijkheid en ik gebruik Adobe producten alleen om mijn oude werk te openen en om te zetten naar zoveel mogelijk tijdsbestendige formaten.
Dat zal nog wel even duren, want ik heb 12 jaar lang met veel plezier en veel gegrumbl Flash gebruikt vanaf Flash2.0 van Macromedia.
Maar ondanks dat dit een afbouw-proces is, vat ik het voor mezelf even samen als:
"Vaarwel Adobe, vaarwel Creative Cloud." We hebben het mooi gehad, maar ik moet verder en jij gaat de verkeerde kant op...
Ik ga de toekomst fris tegemoet, zonder enige kosten voor mijn software.
In ruil zal ik mijn steentje bijdragen op de forums van de open source software..

Goed, nu weer gauw proberen Flash CC aan het werk te krijgen, zodat ik een wijziging kan maken in iets dat ik vorig jaar voor een klant heb gemaakt. (Want met Flash5.5 compileert dit weer niet, omdat het is gemaakt in FlashCC6.0, een versie die nu verdwenen is in de creative Cloud).


zondag 2 maart 2014

Scripts generating scripts - javascript and illustrator

I think I've found a new workflow that may not be new, but might be new to some.
I had the problem of having to generate a lot (3800) of files in illustrator.
These files had elements that would be generated  (by Flash) and had to be integrated into ai files.
Also I had to present it in HTML5 using x3Dom to get an idea of what I was doing.

Now I had made a as3 program, that took in 3D data from Rhino. (We just exported point and bi-arcs in text from Rhino) My script in Flash converted this data into 2D files vector that could be used as textures (when stamped down to PNG's).
We used the PNG-textures for the preview in HTML5, so we could walk through the textured building (this was for an architect), but we also needed the (vector) textures to be saved in a format that a printer could work with, we setlled on PDF, which I could generate from Flash with a library..

First step: generating JS from Flash for a Preview:
I had already interpreted the bi-arcs in Flash, so to do it again in Javascript wouldn't be much of a problem, but it turned out to be easier, to generate the javascript from Flash.
This way, I could spend my time elaborating on the data where I needed it and and leaving out what wasn't important.

Second Step: generating a JS script to generate files in Adobe Illustrator:
Although we first decided the output would be PDF, because the library did not export layers in the PDF page and because spot-colors were a problem, it turned out to be easier for the printer to get AI files instead.
I was able to comply, by doing the same trick again. I used Flash, to generate Javascript (JSX) that extends adobe illustrator and uses it to generate illustrator files.
(My basic generation script, without the parts generated by Flash is below)

This last step seems a quite promising development. We could go from Rhino (a scripted environment) to Flash (a scripted environment) and then use Illustrator to generate print-ready files (in again a scripted environment).
This means, that this workflow could be very helpfull for anyone with the same kind of problem.

Photoshop, In Design and Illustrator all support javascript extensions for scripting. In stead of going through actionscript (flash) to generate the scripts to extend illustrator, I could have used Javascript to generate the same. Also Adobe makes a point of supporting applescript and VBscript as well.
This enables the developer (or scripter) to do his work and most of the debugging in the environment he's most comfortable with and then exporting to whatever environment he wants. It may seem a bit cumbersome at first, but I assure you, once you get your head around it, it's VERY flexible.

One word of caution: Debugging jsx in illustrator sucks. So get a working script and let your script modify it to just add the data.

Here is a tutorial to get you started:
http://creativedroplets.com/tutorial-scripting-for-illustrator-cs6/

There is a LOT of support for scripts from adobe:
http://www.adobe.com/devnet/illustrator/scripting.html

And it's actually well documented this time. It only took me a few hours to write my generation script, which was my first script ever.This was a very nice surprise. Even though I'm not all that familiar with Adobe Illustrator, I had no trouble finding specific things like information about layers and spotcolors. I actually learned a few things about the way illustrator is put together.

I've bitched about Adobe's lack of vision in the past when compared to the things Macromedia used to do (and I'm still behind everything I said), but this seems a very promising new direction, which could result in a very active community.
When something is good, it needs to be said as well: Well done Adobe.

Just to be complete, here is my basic rendering and generation script.
I use Flash to create the data this script will use to generate ai-files, with two layers and two spot-colors.
It's been scrounged together from various sources offcourse, but it will tell you all you need to do, if you just want to generate ai-files by drawing paths into them.

To get you started, copy it into a text-file. name it jsx. The go to illustrator, choose scripts from the menu.
Navigate to the script and select it.
It will ask you to find a directory and it will put three files in it with generated content.
It's well commented, so it should be enough to get you started on your own.
If you like it, drop me a comment, to tell me what you made :)

/**********************************************************

Basic Generation script for illustrator made by Hjalmar with Flash...

*********************************************************/

/** 
 Creates a new document, 
 draws a baffle and 
 Saves every document as AI
*/

// Main Code [Execution of script begins here]

try {
 
 // Get the folder to save the files into
 var destFolder = null;
 destFolder = Folder.selectDialog( 'Select folder for AI files.', '~' );

 if (destFolder != null) 
 {
  var options, i, activeDoc, targetFile; 
  
  // Get the PDF options to be used
     
  for ( i = 0; i < 3; i++ ) 
  {
   // create a document!
   // Preset
   var doc_preset = new DocumentPreset;
   doc_preset.units = RulerUnits.Centimeters; // normal is .Inches;
   var activeDoc = app.documents.addDocument(DocumentColorSpace.CMYK, doc_preset); // add document
         
   // Get the file to save the document as ai into
   targetFile = this.getTargetFile("baffle_"+i, '.ai', destFolder);
   
   // set up the layers!
   var plotterLayer = activeDoc.activeLayer; // there's one made automatically, so we use that one... activeDoc.layers.add();
   plotterLayer.name = "cutcontour";
   var artLayer = activeDoc.layers.add();
   artLayer.name = "stationsblauw";

   // create all colors
   // Define the new color values in CMYK, but we are going to make them spot colors!
   CMYKblue = new CMYKColor();
   CMYKblue.black = 50.0;
   CMYKblue.cyan = 80.4;
   CMYKblue.magenta = 0;
   CMYKblue.yellow = 0;

   CMYKline = new CMYKColor();
   CMYKline.black = 0;
   CMYKline.cyan = 0.0;
   CMYKline.magenta = 32;
   CMYKline.yellow = 32;
   
   // Use the CMYK color object in the creation of spots
   // Create the new spots
   var blauwspot = app.activeDocument.spots.add();
   blauwspot.name = "stationsblauw";
   blauwspot.tint = 100;
   blauwspot.color = CMYKblue;
   
   var linespot = app.activeDocument.spots.add();
   linespot.name = "cutcontour";
   linespot.tint = 100;
   linespot.color = CMYKline;
   
   // Create a spotcolor objects, set the tint value,
   var spotBlue = new SpotColor();
   spotBlue.spot = blauwspot;
   spotBlue.tint = 100;

   var spotLine = new SpotColor();
   spotLine.spot = linespot;
   spotLine.tint = 100;

   // set the outline path as part of the plotterLayer!
   
   // Use the spot color to set the fill color
   var myLine = plotterLayer.pathItems.add();
   //set stroked to true so we can see the path
   myLine.stroked = true;
   myLine.strokeColor = spotLine;
   myLine.closed = true;
   myLine.setEntirePath([[220, 475], [375, 300], [200, 300]]);

   for(t=0;t<10;t++)
   {
    // draw a square on a random place on the artLayer
    var tbp = artLayer.pathItems.add();
    tbp.stroked = false;
    tbp.filled = true;
    tbp.fillColor = spotBlue;
    var tx=250+Math.random()*50;
    var ty=250+Math.random()*50;
    tbp.setEntirePath([[tx, ty], [tx+5, ty], [tx+5, ty+5],[tx, ty+5]]);
   }
   // Save as ai
   var saveOptions = new IllustratorSaveOptions();
   saveOptions.compatibility = Compatibility.ILLUSTRATOR8;
   saveOptions.flattenOutput = OutputFlattening.PRESERVEAPPEARANCE;
   app.activeDocument.saveAs( targetFile, saveOptions );  
   
   // we close the doc to save memory!
   app.activeDocument.close();
   
   //alert( 'Document saved as AI' );
  }
 }else
 {
  throw new Error('No folder selected');
 }
}
catch(e) {
 alert( e.message, "Script Alert", true);
}


/** Returns the file to save or export the document into.
 @param docName the name of the document
 @param ext the extension the file extension to be applied
 @param destFolder the output folder
 @return File object
*/
function getTargetFile(docName, ext, destFolder) {
 var newName = "";

 // if name has no dot (and hence no extension),
 // just append the extension
 if (docName.indexOf('.') < 0) {
  newName = docName + ext;
 } else {
  var dot = docName.lastIndexOf('.');
  newName += docName.substring(0, dot);
  newName += ext;
 }
 
 // Create the file object to save to
 var myFile = new File( destFolder + '/' + newName );
 
 // Preflight access rights
 if (myFile.open("w")) {
  myFile.close();
 }
 else {
  throw new Error('Access is denied');
 }
 return myFile;
}

dinsdag 11 februari 2014

Perspective anyone?

If anyone is interested, I found the complete code from that same period as the rotation of a point in the previous post of a 3D camera (perspective transformation) I once wrote.

I was most ambitiously creating a 3D animation and object editing program. And I had never even heard off openGL.
So it's a little bit of a different approach than OpenGL and it uses CPU exclusively, but I needed it then to do CartoonRendering, back when I invented it.
It uses a camera object, an axis with a screen/plane floating in front of it. For every point in the model, I project it onto the screen.
The whole thing came about when I saw perspective explained on a plate from the Dutch golden age. A guy was looking through a glass plate with one eye closed and could trace the contours of a cube onto the glass plate. It was so simple.

So the eye became an axis, the glass plate a plane and I basically did the same thing in the program.



The fun thing is, it's a much easier to understand model, than the openGL model with a four dimensional array. Which has been optimised for computers, not for human understanding.
Honestly, the first time I saw what openGL was doing, I felt my brain was dripping out of my ears.
Also getting screen coordinates back from openGL can be a bit tiring. But for interactive 3D environments screen-coordinates (or virt-points as I dubbed them back in 1993) are sooooo handy.

This system doesn't use the matrices that you need for openGL either and is quite easy to understand if you keep this picture in your head. It's probably also easier for emulating specific camera's if you know the focal lengths of this lens and the size of the objective, although I never tried.

So anyone up for a tutorial? Just say the word. (Actually, literally comment, because I'm not convinced anyone is interested.. Maybe everybody is perfectly allright with openGL, webGl and whatever else is out ther and it's quite a voluminous tutorial if I want to do it right)



Rotating a point in 3D

It seems so trivial in this age of OpenGL, WebGL and many other beautiful libs, that will do the hard work for you. And then you find yourself in a position, where you need something simple and it's nowhere to be found.

Rotation of a point around the origin or O  or {x:0,y:0,z:0}
How hard can it be.
Well, it's not simple.

Here is the code in as3 and javascript

function rotatePoint(p,rx,ry,rz)
{
    var x,y,z,q={};
    x=p.x*Math.cos(rz)-p.y*Math.sin(rz);
    y=p.x*Math.sin(rz)+p.y*Math.cos(rz);

    q.x=x*Math.cos(ry)-p.z*Math.sin(ry);
    z=x*Math.sin(ry)+p.z*Math.cos(ry);

    q.y=y*Math.cos(rx)-z*Math.sin(rx);
    q.z=y*Math.sin(rx)+z*Math.cos(rx);
    return q;
}

The parameters:
p is a point, so an object with {x:x,y:y,z:z};
rx is the amount you want to rotate around the x axis in radians.
ry is the amount you want to rotate around the y axis in radians.
rz  is the amount you want to rotate around the z axis in radians.

It returns a point with the new rotated coordinates. Don't try to understand the maths, it took me three days to put this together.

So in practice, I have a point 1,0,0 and I want to rotate it around the z axis 45 degrees.
The answer is in this case pretty obvious, it would be 0,707...,0.707....,0 or cos(45),sin(45),0
So how would we go about doing that with the function?

  p.x=1;
  p.y=0;
  p.z=0;
  p=rotatePoint(p,45/180*Math.PI,0,0);
  trace(p.x+","+p.y+","+p.z);

Output:
0.7071067811865476,0.7071067811865475,0

Halleluja, you can now play around with the other axis and stuff.
Any time you need something rotated, this function is your friend.
I've been using it on an off since 1988 just needed it again for my Delft project (about which I will tell you more later, but now, I'm sworn to secrecy :)
I found it in an ancient piece of code from 1996 in C, so I rewrote it to Javascript/As3.
And there you are.

vrijdag 10 januari 2014

Site Takeover animation (Hybrid Site lib and CreateJS)

Site Takeover

Today I'm making a site takeover animation and programming the takeover.
The site is in HTML5 and contains a lot of javascript.



The takeover should be viewable in all browsers, the animation includes sound (and sound transforms) and must fill the whole screen (or as much as possible) while staying transparent.
On a click or touch, the takeover should abort and give back control to the site.

The takeover animation consists of two parts:

  • AT STARTUP: A cartoon man walking into the screen, delivering a message and leaving the screen on the other side. Before he leaves, he points at the menu and invites people to look around.







  • AT IDLE: When the user does nothing for 5 seconds, a cartoon guy pops up and draws attention to an offer.


Technical setup

I like to keep things simple for the client, so all they have to do is include a javascript and call one function when the page is done loading.
I'd do that normally, but this page has a lot of javascript.

Then the takeover.js file creates a new layer containing an transparent, borderless, seamless iframe and fills it with a page.
This is where the magic happens.




The page Includes the takeOverLib, which checks browser capabilities and screen size and decides if we create a flash object, or a HTML5 animation (It is actually not a flash fallback, but more of a flash fallforward).

To keep production feasible the animation.swf and animation.js (using createJS lib) both load the same assets (images and sounds). The sound assets are done in mp3 and ogg both, to accomodate fireFox browser.

Creating the assets

In this case the cartoon-guy was allready designed, I just animated it in Flash to the voice-files that were also allready recorded. I just added the footsteps. There was very little text, so I exported that as curves, keeping the actual text on a reference layer.

I created a preliminary takeover, using only flash, to present to the client and when I got the go ahead I created all assets as CreateJS assets in Flash CC Pro. The audio output I replaced with the original audio (why re-convert it?) and I created the ogg samples manually in Soundforge.
Then I rerouted the audio in the CreateJS manifest manually to have Flash and CreateJS use the same folder.

Programming the Animation

The animation doesn't know how big the screen is. It was decided to have the cartoon man come in with a perspective effect. This meant I had to calculate the starting point (and size) of the man from the position I want him to end up in. (Center screen).
To do this, I put the guy in center screen and used the movement function I created repeatedly until it was out of the screen. Then I would start the animation and as long as the user doesn't resize the browser in the first bit of the animation all will go fine and he will end up in the middle of the screen.
Then I had to make sure that if the user did resize the browser, the animation was recalculated.

I programmed this in Flash initially, but I knew I had to do it again for createJS. That is something that still bothers me about createJS, but it was the easiest way to do this.
Converting this from the original to CreateJS was a job of a few hours.

This is where the hybrid lib definitely wins from Flash/CreateJS, but it doesn't (yet) support vector-animation natively. CreateJS does and it is the only feasably way I found to get vector animation output in anything other than Flash. (Although there is always Swiffy!)
There is an open standard (Animated SVG) and it would be nicer and more honest of adobe to at least offer export to this or svg-frame for that matter. I could then use Flash as an IDE for whatever output I want.

Programming the takeover

The takeover itself was rather simple. A full screen, seamless iframe. The page inside the iframe starts by finding out all it can about windowsize, capabilites etc. Then it sets up a click listener, that aborts everything on the first click!
It also keeps track of how long the animation is supposed to be, so that if you would fail to stop the animation (or if something went wrong) the user would get back system control after a while, no matter what!

Hybrid site lib (v0.5)

The hybrid wasn't responsible for any graphics this time, but did all the browser sniffing and pageheight getting. It also didn't stick to a preset aspect like the game lib. Well, it's a start.

donderdag 9 januari 2014

Facebook developer worden om insights te gebruiken

Stel, ik  heb een spel voor u gemaakt op facebook en u wilt gebruik maken van facebook insights om te zien hoe vaak het spel gespeeld wordt en boodschappen gedeeld worden.
Dan zult u zich eerst moeten registreren als developer op Facebook.
Dit stelt niks voor, feitelijk wil Facebook alleen uw telefoonnummer registreren en verifieren.

Het proces gaat als volgt:

    • Wordt vrienden met SnoepGames (dan is het makkelijker u uit te nodigen voor de gezamelijke app en kan ik me ook niet vergissen als u  een algemene naam hebt.) Dit is mijn bedrijfsaccount, ik heb ook een familie en vrienden account.

    • Er komt een developer request om insights te gebruiken.


    • U wordt doorgestuurd naar developers.facebook.com
      Daar volgt u een zeer eenvoudig vier stappen plan. Als u twijfelt ziet u hier voorbeelden van hoe ik het zou invullen, als ik u was.

      Klik op de groene knop en de wizard gaat van start.







    • Accepteer de voorwaarden door op het vinkje te klikken, klik dan op doorgaan.





    • Vul een telefoon nummer (06) in en wacht op het smsje, vul dan de bevestigingscode in. Facebook vraagt met wie de nieuwe informatie mag worden gedeeld: kies: alleen ik!

    • Vul het grote formulier als volgt in: Negeer de bovenste twee, Kies web, overig en Games. Vergeet niet de twee vinkjes onderaan UIT TE ZETTEN! Facebook negeert hier de Nederlandse wetgeving over OPTING -in! Het is mogelijk om deze later uit te zetten, maar dat is lastiger.

    • De laatste stap is op klaar klikken.
      u wordt gefeliciteerd met uw developer-schap.

    • Als u nu in facebook komt, staat er een kopje ontwikkelaar aan de linkerkant. Klik daar op de app, waarvoor ik u heb toegevoegd en u hebt toegang tot de insights-statistieken













    • Klik op alles weergeven om bij de grafiekjes te komen. Voor de duidelijkheid, dit is voor de campagne begon, we zien hier de insights van het test-traject. Dit vind u ook op: https://www.facebook.com/insights/