JSFL


Bievenidos nuevamente. Desde el año pasado que nos posteo nada, así que aprovecho este momento para desearon un gran año con mucho trabajo, nuevo retos, proyectos interesante y mucho aprendizaje. Vale, vale, también con mucha, muchísima felicidad :D

INTRODUCCIÓN

En esta ocasión no habrá mucho texto ya que todo lo he hecho en video, así que este también es mi primer videotutorial, espero migrar poco a poco algunos de los post a este formato.

Eso si, contaré rápidamente que veremos y para que sirve esto. Es un comando para Guardar el documento y Probar la película, es como hacer CRT+S y CTR+ENTER, pero de una sola vez. Además y creo que esto es de lo más importante, veremos como modificar los atajos de teclado para sustituir el atajo CTR+ENTER para que ejecute nuestro comando.

DESCARGAS

Bueno, las descargas son en este caso son:

  • Extensión auto instalable mediante Adobe Extensión Manager. Comando Save and Test MXP.
  • Comando fichero JSFL para el que lo quiera instalar a mano.

AGRADECIMIENTOS

En esta ocasión quiero agradecer a mi amigo Iván que me ayudó a montar el video y sobre todo a Juan quien me permitió utilizar su creación musical para ponerla de fondo.

Bienvenidos a este nuevo tutorial de jsfl, en esta ocasión continuaremos viendo los Paneles y como desarrollarlos con Adobe Flex.

INTRODUCCIÓN

Si recordamos el anterior post dónde empezamos a hablar sobre el uso de Flex para desarrollar Paneles y teniendo en cuenta que a mi querido amigo Jorge no le acabó de convencer :P.

Tweet de solisargBueno para ser sinceros hay que contar la historia completa, no le acabó de convencer al principio, luego al ver de que se trataba ya le gustó:

Ahora si, ya veo de que se trataba ese tweet

A continuación veremos como hacer mucho más, veremos como utilizar las bondades de Flex para crear fácilmente ricas interfaces y como comunicarlo con JSFL para ejecutar las tareas que nos interesen.

En esta ocasión espero que os guste a todos :P

DESARROLLO

PARTE FLEX

En el post anterior vimos como utilizar el método MMExecute para poder ejecutar código JSFL desde nuestras películas swf, pero para los que somos un poco especiales a la hora de programar y que nos gusta tener las cosas organizadas, separadas, modularizadas para poder escalarlas fácilmente y reutilizarlasuyy ya me fuí por las ramas … bueno, el tema es que no es la mejor solución mezclar la lógica JSFL con el interfaz, porque hacer cambios y probar puedes ser mortal y generar muchos errores así como una enorme pérdida de tiempo.

Bueno, lo anterior sirve de introducción para presentarles el método runScript del objeto fl, este método nos permite desde código JSFL ejecutar un script externo al código. Este método recibe como parámetro obligatorio la ruta del script JSFL que deseamos ejectuar, como parámetros opcionales el nombre del método y los parámetros que enviamos al método.

fl.runScript("file:///C|/testScript.jsfl", "testFunct", 10, 1);

Además vamos a utilizar la propiedad configURI del objeto fl, esta propiedad nos devuelve el path del usuario del directorio Configuration expresado en formato file:/// , en el cual encontramos los directorios Commands y WindowSWF por ejemplo. Y esto lo queremos para hacer algo parecido a esto:

fl.runScript( fl.configURI + "Commands/Test.jsfl" );

Bueno, esto nos servirá al final para poder ejecutar desde nuestras aplicaciones Flex código JSFL que tengamos centralizado en la carpeta Commands por ejemplo, algo parecido a lo siguiente:

MMExecute('fl.runScript(fl.configURI + "Commands/Test.jsfl", "testFunct", 10, 1)');

Vale, hasta ahora vamos bien. Todo lo que hemos visto lo vamos a utilizar para crear una panel que particularmente me resulta muy útil. Crearemos el Panel Gallery.

PARTE JSFL

Ahora si vamos que se va a poner bueno el tema. Jejeje, es necesario un poco de relax porque sino resulta difícil leer y escribir también, porque aquí somos dos, tu querido lector y yo.

Lo que pasa es que está semana ha empezado bien, pero de pronto el lunes por la noche nos dimos cuenta que ya no quedaban más episodios de la 4ª temporada de Dexter por ver, así que nos pusimos a buscar algo más y encontramos la 5ª temporada de Héroes, así que estas noches me han tenido un poco entre la serie y escribir, preparar y desarrollar este tutorial. Bueno ya que nos relajamos y hablamos un poco, creo que podemos continuar.

Ya por último y para terminar con este pequeño lapso de relax, quiero recomendar una serie súper interesante que vi hace poco, me refiero a Defying gravity, este es otro de los tesoros que he descubierto gracias a Twitter.

Panel Gallery, este panel sirve para tener un pequeño visor de imágenes del directorio que configuremos en nuestro equipo dentro de Flash, desde ahí podemos ver, seleccionar e importar las imágenes que deseemos al documento que estemos editando.

Para desarrollar este panel necesitaremos obtener la ruta de la carpeta que deseamos visualizar, esto lo podemos hacer con el método browseForFolderURL del objeto fl, este método recibe como parámetro una cadena en la que especificamos el mensaje que mostrará al usuario y nos devolverá la ruta que especifique el usuario en formato file:///. Por ejemplo:

var folderURI = fl.browseForFolderURL("Select a folder.");

Una vez que tenemos la ruta lo siguiente es listar las imágenes que tenemos en ese directorio, esto lo hacemos con el método listFolder del objeto FLfile, este método recibe como parámetro obligatorio la ruta de la cual queremos listar directorio o imágenes (en nuestro caso es la ruta que obtuvimos en el paso anterior) y como parámetro opcional indicamos el tipo de lista que deseamos, los valores admitidos son: “files” o “directories“. En nuestro caso utilizaremos “files“, pero no sólo eso, el primer parámetro también nos permite añadir una máscara para que la búsqueda filtre por un tipo de fichero, está máscara funciona igual que en un terminal, por ejemplo la máscara que utilizaremos nosotros será: “*.jpg“. El ejemplo quedaría de la siguiente forma:

var fileMask = "*.jpg";
var list = FLfile.listFolder(folderURI + "/" + fileMask, "files");

Ahora si ya estamos muy cerca. Bueno, una vez que obtenemos la lista de imágenes vamos a almacenarlas en un componente Tree para mostrarlas al usuario y para facilitar el uso utilizaremos el evento change para cargar la imagen seleccionada y mostrarla en un componente Image, por último utilizaremos el evento click del componente Image para importar la imagen seleccionada al documento fla. Esto último lo hacemos con el método importFile del objeto Document, este método recibe como parámetro obligatorio la ruta del fichero que deseamos importar en formato file:///, y como parámetro opcional un valor booleano que indica si deseamos importar el fichero a la biblioteca o no, el valor por defecto es false y lo que hace es importarla a la biblioteca y además instanciarla en el escenario. Por ejemplo:

fl.getDocumentDOM.importFile(URI);

Y con esto lo hemos resuelto. YATA!!!

NOTAS

Para acompañar este tutorial y como premio por haberte leído todo he creado como es habitual un fichero de ejemplo, pero con unas perlitas extras de funcionalidad.

He dividido el panel en 4 partes:

  • Document, encontraremos herramientas para modificar on the fly el color de fondo del documento y las dimensiones.
  • Gallery, el resultado del tutorial que hemos explicado.
  • Library, una herramienta para renombrar varios items de la biblioteca al mismo tiempo, pudiendo añadir prefijo, sufijo o modificar completamente el nombre.
  • Utils, un botón para recargar las herramientas, muy útil cuando se desarrollan Tools (herramientas) con JSFL.

Disculpad el desorden del post, es lo que tiene escribir a ratos en el tren y por la noche mientras se ven series. En un principio tenía una idea de como quería escribir un post, pero eso fue hace tanto tiempo que al final tenía otra idea diferente, así que las cosas han salido como la pueden ver aquí. Espero que os sea de utilidad.

DESCARGAS

Bueno, las descargas son en este caso son:

  • Extensión auto instalable mediante Adobe Extensión Manager. Panel nomeva MXP.
  • Paquete ZIP con Panel swf y ficheros JSFL necesarios para instalar manualmente el Panel.
  • Proyecto Flex con todo el código necesario para compilar y ver las tripas del Panel.

EJEMPLO

Ejemplo Panel nomeva – Flex + JSFL 2ª parte from Luis Adrián Rosas Wiedfeldt on Vimeo.

ALGO MÁS

Si, lo único que falta son vuestros comentarios, opiniones para tener un feedback y saber que os gusta y que os disgusta, jejeje.

Entradas relacionadas

Bienvenidos, en esta ocasión retomaremos el tema de los Paneles pero enfocado a su creación mediante Adobe Flex.

Antes o después de leer este tutorial sería interesante leer el este otro post sobre la introducción a la creación de Paneles.

INTRODUCCIÓN

La idea es crear un panel que nos ayude a modificar el fondo del documento FLA, pero más rápidamente, si, sé que cambiar el fondo del documento es muy fácil, pero soy un poco maniático y la verdad tener que abrir una ventana, seleccionar un color y luego dar click en aceptar son muchos pasos, me gustaría algo mucho más rápido, algo como hacer rollOver sobre un componente ColorPicker y listo.

DESARROLLO

Para ejecutar código JSFL en una película swf generada con Flex utilizaremos el método MMExecute que encontramos en el paquete adobe.utils por ejemplo:

import adobe.utils.MMExecute;
MMExecute("jsfl code");

El método MMExecute recibe un parámetro de tipo String en el cual indicaremos el código JSFL que deseamos ejecutar. Además devuelve un valor también de tipo String que es la representación en cadena del resultado de la ejecución del código.

Parte JSFL

Vale, ahora que sabemos como ejecutar código JSFL necesitamos saber que código ejecutar. Lo que queremos modificar es una propiedad del documento FLA, así es que antes que otra cosa debemos obtener una referencia al documento, esto lo hacemos con el siguiente código:

var oDoc = fl.getDocumentDOM();

Y para acceder y modificar el color de fondo utilizamos la propiedad backgroundColor que es de lectura y escritura:

oDoc.backgroundColor

Listo, por lo menos la parte de JSFL, ahora tenemos que integrar este código en una aplicación Flex.

Parte FLEX

Utilizaremos un componente ColorPicker este componente entre otras cosas emite los eventos:

  • change
  • close
  • itemRollOver
  • itemRollOut
  • open

Los que en nuestro caso nos interesan son los eventos change e itemRollOver así que como en cualquier otra aplicación utilizamos el siguiente código:

<mx:ColorPicker id="cpBackgroundColor" x="89" y="10" change="onChange(event);" itemRollOver="onItemRollOver(event);" />

Ahora simplemente en los métodos onChange y onItemRollOver es donde tendremos que utilizar el método MMExecute de la siguiente manera:

import mx.events.ColorPickerEvent;
import adobe.utils.MMExecute;

private function onChange(_oEvent:ColorPickerEvent):void
{
    if (this.isDocumentExists())
        MMExecute("fl.getDocumentDOM().backgroundColor = Number(" + _oEvent.color + ");");
}

private function onItemRollOver(_oEvent:ColorPickerEvent):void
{
    if (this.isDocumentExists())
        MMExecute("fl.getDocumentDOM().backgroundColor = Number(" + _oEvent.color + ");");
}

private function isDocumentExists():Boolean
{
    var ret:Boolean = false;
    if (MMExecute("fl.getDocumentDOM();") != "null")
        ret = true;

    return ret;
}

INSTALACIÓN

Listo, el resultado no lo podremos ver en ejecución a menos que llevemos el swf resultante a la carpeta de Paneles de Flash, es decir al directorio WindowSWF dentro del directorio Configuration de la instalación.

Según el sistema operativo:

Windows® VistaTM:

  • unidad de arranque\Users\nombre de usuario\Local Settings\Application Data\Adobe\Flash

CS4\idioma\Configuration\

Windows XP:

  • unidad de arranque\Documents and Settings\nombre de usuario\Local Settings\Application Data\Adobe\Flash CS4\idioma\Configuration\

Mac OS® X:

  • Macintosh HD/Usuarios/nombre de usuario/Librería/Application Support/Adobe/Flash

CS4/idioma/Configuration/

EJECUCIÓN

Para ejecutar el Panel debemos acceder al menú Ventana -> Otros paneles -> Change Background Color a continuación un ejemplo de como ejecutar y su funcionamiento:

Ver ejemplo

DESCARGAS

Como es habitual a continuación podéis descargar los fuentes y el instalador del Panel:

  • Fichero MXML de Flex por si te interesa ver el código.
  • Fichero SWF del Panel para instalar manualmente el Panel.
  • Instalador MXP del Panel para instalar automáticamente la extensión.

Saludos, cualquier duda o comentario será bienvenido.

Entradas relacionadas

INTRODUCCIÓN

El objetivo de JSFL es ayudar a agilizar el proceso de edición en Adobe Flash Professional. Pero, ¿qué quiere decir esto? bueno, eso nos lo responde la ayuda de Ampliación de Flash CS4 Professional con ejemplos tales como automatizar tareas repetitivas o la creación de herramientas personalizadas.

La API JavaScript permite escribir scripts para aplicaciones Flash que ayudan a agilizar el proceso de edición. Por ejemplo, se pueden escribir scripts para automatizar tareas repetitivas o añadir herramientas personalizadas al panel Herramientas.

TUTORIAL

En este tutorial vamos a ver como automatizar una tarea muy habitual y repetitiva en el día a día de un desarrollador / diseñador Flash. Vamos a ver como crear un comando para embeber caracteres a un campo de texto dinámico y además vamos a ver como utilizar el Panel Historial.

Primero abriremos el Panel Historial, esto lo hacemos desde el menú Ventana -> Otros paneles -> Historial o con los atajos de teclado Ctr + F10 en Windows y Cmd + F10 en Mac OS X.


panel historial adobe flash

Ahora comprobaremos el estado de visualización del Panel, debe estar en “JavaScript del panel”, si no es así lo modificamos.

visualizacion panel historial adobe flash

Ahora si con el Panel abierto haremos esa tarea tan repetitiva que es embeber fuentes en un campo de texto dinámico. Para esto hacemos lo siguiente:

  • Creamos un campo de texto con la herramienta texto.
  • Volvemos dinámico el campo de texto utilizando el Panel de propiedades.
  • Seleccionamos en el desplegable de Suavizado la opción “Suavizado para animación“.

panel propiedades texto adobe flash

  • Hacemos click en el botónIncorporación de caracteres…“.
  • En la ventana que se abre seleccionamos los juegos de caracteres a embeber.
  • En el campo de texto añadimos los caracteres especiales, tales como letras con tildes, diéresis, ñ y ç entre otros.

incorporacion de caracteres adobe flash

Aceptamos y listo ya tenemos nuestro campo de texto dinámico con las fuentes embebidas, ahora nos vamos al Panel Historial y veremos todo lo que hemos estado haciendo, pero con el pequeño añadido que ahora veremos el código JSFL que tenemos que utilizar en nuestro comando.

panel historial comandos embed fonts adobe flash

En la parte inferior derecha del Panel Historial tenemos el botón Guardar, éste se activa cuando seleccionamos alguna línea de código, en este caso lo que queremos hacer es guardar las líneas de código en las que indicamos al campo de texto que utilice Suavizado para animación, los juegos de caracteres y los caracteres especiales. Así que una vez seleccionadas hacemos click en el botón Guardar y ahora simplemente tenemos que escribir el nombre del comando.

ventana guardar como comando adobe flash

Listo, con esto hemos creado un comando sin tener que picar nada de código, es una forma muy simple y eficiente con la que cualquiera puede crear comandos sin necesidad de saber programar.

Ahora para ejecutar el comando simplemente vamos al menú Comandos y seleccionamos de la lista el comando que hemos creado, Embeber caracteres.

menu comandos comando embeber caracteres adobe flash

DESCARGAS

Como es habitual dejo descargas del fichero JSFL y también del fichero MXP para instalar el comando.

  • Comando Embeber caracteres (versión JSFL).
  • Instalador de Comando Embeber caracteres.

NOTAS

Para utilizar el comando debes seleccionar un campo de texto. Para cualquier cosa, dudas, comentarios o sugerencias aquí estaré.

Saludos!!!

Entradas relacionadas

La localización (traducción) de contenidos es un tema muy importante, en ocasiones es el punto clave de los desarrollos, pero en muchas ocasiones no se tiene en cuenta. En mi caso he tenido que pasar por esta situación más de una vez.
Cuando se nos platea la situación siempre pensamos en una configuración inteligente de los contenidos basada en XML, crear un gestor, objetos, eventos, listeners, switch on the fly para cambiar de idioma y muchas ideas súper guays, pero como siempre tenemos al señor tiempo que viene a presionar, por otro lado el cliente ya tiene el curso completo y funcional, lo único que quiere ahora es que su producto esté en X o Y idioma, vamos que eso tiene que estar chupado.
Pero que pasa cuando quien ha desarrollado esos contenidos no pensó en que algún día se localizarían y utilizó mogollón de campos de texto estáticos, por no hablar de imágenes o diseños, pero esa es otra historia.
Bueno, ahora que más o menos he contado un poco el panorama, jejeje vamos a ver para que sirve todo eso, resumiendo, tenemos, por que si, un fla de su padre y de su madre con un montón de campos de texto estáticos distribuidos por símbolos, gráficos, botones, clips de película y en distintos fotogramas de sus líneas de tiempo respectivas, es decir, un verdadero caos del bueno.
Claro, también tenemos un cliente que nos pide para mañana la traducción de ese curso a Chino, Alemán e Italiano.
¿Qué hacemos?
Le decimos al cliente que estamos hasta arriba de trabajo y que no podremos dar prioridad a su trabajo, vamos que no lo vamos a hacer.
Le decimos al cliente que no podemos hacerlo en ese tiempo y que necesitaremos dos semanas por lo menos y que el trabajo será muy costoso.
Le decimos que vale.
Pero que!!!!, ¿cómo que vale? pero este tío está loco, pero si esa tarea es imposible.
Bueno, ahora es donde entra en juego nuestro querido y siempre infravalorado JSFL.
IDEA E HISTORIETA
Tenemos una línea de tiempo y muchos elementos en una biblioteca, pues simplemente tenemos que recorrer todas las líneas de tiempo y encontrar todos los campos de texto estáticos, convertirlos en campos de texto dinámicos, asignarles una variable, leer su contenido y guardarlo en un fichero XML.
Como trabajamos en una súper empresa enorme con múltiples departamentos, contamos con un departamento de traducción y muchos más, nos ponemos en contacto con nuestro amigo Axel del departamento de traducción y le pedimos que nos traduzca el fichero XML a los idiomas que ha pedido el cliente, en unas horas nos lo devuelve. ¡Qué gusto trabajar en esta empresa! todos son tan eficientes que dan ganas de dar el 200% de cada uno.
Bueno, ahora ya tenemos los ficheros XML en Chino, Alemán e Italiano. Pero recordemos, como hemos dicho que trabajamos en una súper empresa en la que todos son la hostia de eficientes, nosotros no vamos a ser menos, así que mientras Axel trabajaba en la traducción del XML, nosotros hemos estado creado el súper lector de XML que simplemente creará variables y asignará valores, para que cuando los textos dinámicos las necesiten ya estén ahí. Así que mira que coincidencia, hemos terminado al mismo tiempo que Axel, con todo el desarrollo que hemos hecho, más esos XML’s ya tenemos el contenido en 3 idiomas y nos ha tomado menos de un día.
QUE NECESITAMOS

INTRODUCCIÓN

La localización (traducción) de contenidos es un tema muy importante, en ocasiones es el punto clave de los desarrollos, pero en muchas ocasiones no se tiene en cuenta. En mi caso he tenido que pasar por esta situación más de una vez.

Cuando se nos platea la situación siempre pensamos en una configuración inteligente de los contenidos basada en XML, crear un gestor, objetos, eventos, listeners, switch on the fly para cambiar de idioma y muchas ideas súper guays, pero como siempre tenemos al señor tiempo que viene a presionar, por otro lado el cliente ya tiene el curso completo y funcional, lo único que quiere ahora es que su producto esté en X o Y idioma, vamos que eso tiene que estar chupado.

Pero que pasa cuando quien ha desarrollado esos contenidos no pensó en que algún día se localizarían y utilizó mogollón de campos de texto estáticos, por no hablar de imágenes o diseños, pero esa es otra historia.

Bueno, ahora que más o menos he contado un poco el panorama, jejeje vamos a ver para que sirve todo eso, resumiendo, tenemos, por que si, un fla de su padre y de su madre con un montón de campos de texto estáticos distribuidos por símbolos, gráficos, botones, clips de película y en distintos fotogramas de sus líneas de tiempo respectivas, es decir, un verdadero caos del bueno.

Claro, también tenemos un cliente que nos pide para mañana la traducción de ese curso a Chino, Alemán e Italiano.

¿Qué hacemos?

  • Le decimos al cliente que estamos hasta arriba de trabajo y que no podremos dar prioridad a su trabajo, vamos que no lo vamos a hacer.
  • Le decimos al cliente que no podemos hacerlo en ese tiempo y que necesitaremos dos semanas por lo menos y que el trabajo será muy costoso.
  • Le decimos que vale.

Pero qué!!!!, ¿cómo que vale? pero este tío está loco, pero si esa tarea es imposible.

Bueno, ahora es donde entra en juego nuestro querido y siempre infravalorado JSFL.

IDEA E HISTORIETA

Tenemos una línea de tiempo y muchos elementos en una biblioteca, pues simplemente tenemos que recorrer todas las líneas de tiempo y encontrar todos los campos de texto estáticos, convertirlos en campos de texto dinámicos, asignarles una variable, leer su contenido y guardarlo en un fichero XML.

Como trabajamos en una súper empresa enorme con múltiples departamentos, contamos con un departamento de traducción y muchos más, nos ponemos en contacto con nuestro amigo Axel del departamento de traducción y le pedimos que nos traduzca el fichero XML a los idiomas que ha pedido el cliente, en unas horas nos lo devuelve. ¡Qué gusto trabajar en esta empresa! todos son tan eficientes que dan ganas de dar el 200% de cada uno.

Bueno, ahora ya tenemos los ficheros XML en Chino, Alemán e Italiano. Pero recordemos, como hemos dicho que trabajamos en una súper empresa en la que todos son la ostia de eficientes, nosotros no vamos a ser menos, así que mientras Axel trabajaba en la traducción del XML, nosotros hemos estado creado el súper lector de XML que simplemente creará variables y asignará valores, para que cuando los textos dinámicos las necesiten ya estén ahí. Así que mira que coincidencia, hemos terminado al mismo tiempo que Axel, con todo el desarrollo que hemos hecho, más esos XML’s ya tenemos el contenido en 3 idiomas y nos ha tomado menos de un día.

QUE NECESITAMOS

Primero un repaso rápido al entorno de Flash, en la imagen que se muestra a continuación podemos ver listados los elementos con los que trabajamos a diario y que para este Comando vamos a necesitar.

esquema objetos jsfl

  1. Documento fl.getDocumentDOM()
  2. Línea de tiempo fl.getTimeline()
  3. Capas fl.getTimeline().layers
  4. Biblioteca fl.getDocumentDOM().library
  5. Panel de Propiedades fl.setProperty(“property”, “value”);

Y ahora si, manos a la obra maestro.

Primero que nada vamos a recorrer la línea de tiempo principal para buscar campos de texto, eso ya nos da pistas sobre lo que tenemos que hacer, veamos, hemos dicho que vamos a recorrer la línea de tiempo principal, entonces esto nos indica que necesitaremos una referencia al documento, esto lo resolvemos fácilmente utilizando el comando:

var oDoc = fl.getDocumentDOM();

Una vez que tenemos una referencia al documento ahora si ya podemos obtener una referencia a la línea de tiempo, esto lo hacemos con el siguiente dódigo:

var oTimeline = oDoc.getTimeline();

Una vez que tenemos una referencia a la línea de tiempo ahora tenemos que obtener una referencia a las capas (layers), esta nos la proporciona el objeto línea de tiempo, lo que nos devuelve es un Array (que guay!!!, de verdad que es súper cómodo trabajar con los Arrays), así que aquí empezaremos a ejecutar bucles for anidados. Utilizando un código similar a este:

var aLayers = oTimeline.layers;
var nTotalLayers = aLayers.length;
for(var i = 0; i < nTotalLayers; i++) { ... }

Ahora que recorremos las capas, …

¿Porqué recorremos las capas?

Muy buena pregunta, un punto para el que hizo esa pregunta. La respuesta es sencilla, recorremos las capas por que para buscar los campos de texto tenemos que buscar en los fotogramas clave y la única forma que tenemos de garantizar una búsqueda completa es recorriendo todos los fotogramas de la línea de tiempo.

Pero qué!!!!

A ver, a ver, lo vas a hacer tú? o tú? o yo, no, lo va a hacer automáticamente Flash por nosotros, así que hay de que preocuparse.

… vamos a utilizar la propiedad frames (fotogramas) del objeto Layer (capa) que también nos devuelve un Array (ahora si que ya no quepo de gozo), para buscar los elementos que tiene ese fotograma, tendríamos un código similar a este:

var oLayer = aLayers[i];
var aFrames = oLayer.frames;
var nTotalFrames = aFrames.length;
for(var j = 0; j < nTotalLayers; j++) { ... }

Con esto llegamos casi al punto que nos interesa, el campo de texto, pero nos falta un pequeño paso, el objeto frame tiene una propiedad muy útil, me refiero a la propiedad elements, esta propiedad curiosamente también nos devuelve un Array (he dicho que me gustan mucho los Arrays, es que son la mar de útiles), el código que utilizaríamos sería algo como lo siguiente:

var oFrame = aFrames[j];
var aElements = oFrame.elements;
var nTotalElements = aElements.length;
for(var k = 0; k < nTotalLayers; k++) { ... }

Ahora si, hemos llegado, después de tres bucles anidados, ya tenemos acceso a los elementos del fotograma, así que simplemente tenemos que preguntar el tipo de elemento y en caso de ser de tipo texto podemos modificar sus propiedades y leer el texto que tiene, el código sería más o menos parecido al siguiente:

var oElement = aElements[k];
if (oElement.elementType == "text") { ... }

Bueno, que en el párrafo de arriba escribí de más, así que ahora tengo que volver a escribir otra vez lo de modificar las propiedades del campo de texto y leer su texto, esto lo haremos con el siguiente código:

oElement.textType = "type";
oElement.variableName = "variable_name";
oElement.getTextString();

Y listo, ya lo tenemos.

Menos mal, ya me estaba cansando.

Hey!!! que puedo leer vuestras mentes, a ver tú y tú, los puntos que os habéis ganado hace rato ahora los habéis perdido.

No, no estoy de acuerdo. Si, me estoy cansando, ¿y qué? es normal, con estos tutoriales tan grandes como quieres conservar la atención tanto tiempo. Si quieres mi atención deberías hacer algo más interactivo, entretenido, divertido, cómico, algo en lo podamos participar y no quedarnos todo el rato leyendo. Pero …

Vale, vale, lo siento. Es que estoy aprendiendo. Pero tomo nota de tus comentario, es más, por ser tan honesto te has ganado 150 puntos. Veis chicos, si todos participaseis cuando menos un poco así …

Ahora veamos el código completo:

//Delcaración de variables
var oDoc;
var oLib;
var SEPARATOR = ";";
var PREFFIX_VAR_NAME = "_root.varCommandTextLocalizable_";
var nCounter;

var sXML;

//Llamada a los métodos de configuración e inicialización del comando
this.config();
this.init();

/**
 * @method		config
 * @description	Método encargado de configurar el comando
 * @return		Void
 */
function config()
{
	//Indicamos que no queremos ver el mensaje sobre un script de ejecución demasiado larga
	fl.showIdleMessage(false);

	//Limpiamos la ventana de salida
	fl.outputPanel.clear();

	if(fl.getDocumentDOM())
	{
		//Obtenemos la referencia al documento y a la biblioteca
		this.oDoc = fl.getDocumentDOM();
		this.oLib = this.oDoc.library;
	}
	else
	{
		//En caso que no haya un documento abierto mostrarmo un mensaje de alerta.
		alert("Debes tener un documento abierto.");
	}
}

/**
 * @method		init
 * @description	Método encargado de inicializar el comando
 * @return		Void
 */
function init()
{
	//Delcaración de variables
	var aItems = this.oLib.items;
	var nTotalItems = aItems.length;
	var oItem;
	this.nCounter = 1;

	//Inicializamos el valor del XML abriendo la etiqueta principal
	this.sXML  = "<DATA>\n";

	//Llamamos al método analizeTimeline para que analice le línea de tiempo principal
	this.analizeTimeline();

	for (var i = 0; i < nTotalItems; i++)
	{
		oItem = aItems[i];
		if ((oItem.itemType == "movie clip") || ( oItem.itemType == "graphic") || (oItem.itemType == "button") )
		{
			this.oLib.editItem(oItem.name);
			this.analizeTimeline();
		}
	}

	//Finalizamos el valor del XML cerrando la etiqueta principal
	this.sXML += "</DATA>";

	//Llamada al método createXmlFile
	this.createXmlFile();

	//Limpiamos la memoria de Flash eliminando las variable que hemos creado
	delete aItems, nTotalItems, oItem;
}

/**
 * @method		analizeTimeline
 * @description	Método encargado analizar una línea de tiempo para buscar campos de texto
 *				si encuentra campos de texto, los convierte en dinámicos y les añade
 *				una variable.
 *				Toda la información que va encontrando la almacena en la variable sXML
 * @return		Void
 */
function analizeTimeline()
{
	//Delcaración de variables
	var oTimeline = this.oDoc.getTimeline();
	var aLayers = oTimeline.layers;
	var nTotalLayers = aLayers.length;
	var oLayer;

	//Recorremos las capas
	for (var j = 0; j < nTotalLayers; j++)
	{
		oLayer = aLayers[j];
		oLayer.locked = false;
		oLayer.visible = true;
		if ((oLayer.layerType != "guide") || (oLayer.layerType != "folder"))
		{
			//Delcaración de variables
			var aFrames = oLayer.frames;
			var nTotalFrames = aFrames.length;
			var oFrame;
			var aElements;

			//Recorremos los fotogramas de la capa
			for (var k = 0; k < nTotalFrames; k++)
			{
				oFrame = aFrames[k];
				if (oFrame.elements.length > 0)
				{
					aElements = oFrame.elements;

					//Delcaración de variables
					var nTotalElements = aElements.length;
					var oElement;

					//Recorremos los elementos del fotograma
					for (var l = 0; l < nTotalElements; l++)
					{
						oElement = aElements[l];
						if (oElement.elementType == "text" && oElement.textType != "input")
						{
							//Delcaración de variables
							var sDataItem = "Nombre de la timeline: " + oTimeline.name;
							var sDataLayer = "Nombre de la capa: " + oLayer.name;
							var sDataFrame = "Número de fotograma: " + (k + 1);
							var sDataElement = "Nombre del elemento: " + oElement.name;
							var sElementText = "Texto del elemento: " + oElement.getTextString();
							var sElementFormat = "Formato del elemento: " + "";
							//fl.trace(sDataItem + this.SEPARATOR + sDataLayer + this.SEPARATOR + sDataFrame + this.SEPARATOR + sDataElement + this.SEPARATOR + sElementText);

							oElement.textType = "dynamic";
							oElement.variableName = this.PREFFIX_VAR_NAME + this.nCounter;

							this.sXML += "	<node varName=\"" + this.PREFFIX_VAR_NAME + this.nCounter + "\">\n";
							this.sXML += "		<![CDATA[" + oElement.getTextString() + "]]>\n";
							this.sXML += "	</node>\n";

							this.nCounter++;
						}
					}

					//Limpiamos la memoria de Flash eliminando las variable que hemos creado
					delete nTotalElements, oElement;

				}

				//Incrementamos el valor de k con la duración del fotograma, esto es para que en el siguiente
				//ciclo del bucle vayamos director al siguiente fotograma clave
				k += oFrame.duration - 1;
			}

			//Limpiamos la memoria de Flash eliminando las variable que hemos creado
			delete aFrames, nTotalFrames, oFrame, aElements;
		}

		this.oDoc.exitEditMode();
	}

	//Limpiamos la memoria de Flash eliminando las variable que hemos creado
	delete oTimeline, aLayers, nTotalLayers, oLayer;
}

/**
 * @method		createXmlFile
 * @description	Método encargado de crear el fichero XML con la relación entre textos y variables
 * @return		Void
 */
function createXmlFile()
{
	//Declaración de variables
	var sPath = this.oDoc.pathURI.split(this.oDoc.name).shift();
	var sFileURI = sPath + "textos_extraidos_automaticamente.xml";

	//Comprobación, si existe el fichero lo eliminamos
	if (FLfile.exists(sFileURI))
		FLfile.remove(sFileURI);

	//Creamos el fichero XML
	FLfile.write(sFileURI, this.sXML);

	//Limpiamos la memoria de Flash eliminando las variable que hemos creado
	delete sPath, sFileURI;
}

Bueno, en este código encontramos además de lo explicado en este tutorial para recorrer las líneas de tiempo, modificar propiedades de campos de texto y extraer textos, código para crear ficheros de texto, en el caso del ejemplo crear un fichero XML con la relación entre la variable asignada al campo de texto y el texto.

El código está comentado, pero si hace falta alguna explicación, si tenéis alguna duda, comentario, mejora, sugerencia, pues aquí estaré gustoso de seguir compartiendo.

DESCARGAS

Como es habitual dejo descargas del fichero JSFL, también el fichero MXP instalable y un zip con el paquete del JSFL y un FLA de ejemplo para extraer los textos.

  • Comando Extractor de Textos (versión JSFL).
  • Instalador de Comando Extractor de Textos.
  • Paquete con JSFL y FLA de ejemplo.

Saludos!!!

NOTAS

Se que algunas personas tendrán mucho que decir, así que por favor háganlo, el tema es complicado, la localización de contenidos es algo muy chungo en ocasiones tal como lo plateo en este ejemplo.

También es cierto que con este ejemplo no salvamos otros obstáculos tales como imágenes que tienen textos y que con la solución de modificar los campos de texto podríamos estropear el funcionamiento de algunos campos de texto que ya fuesen dinámicos y que utilizaran variables.

Ahora si, después de estas notas y una última aclaración, mi objetivo es explicar el funcionamiento de los objetos de JSFL, el ejemplo se presta para sacarle partido al lenguaje, así que por eso lo he desarrollado.

Entradas relacionadas

Tablero

Esta es la tercera entrega de los tutoriales sobre JSFL que en su momento me propuse escribir, con ésta cerraré el paquete de introducción, pero no todo termina aquí, pues han cambiado mucho las cosas desde que empecé a escribir, he aprendido nuevas cosas, me he tenido que enfrentar a nuevos retos y tengo nuevas ideas sobre que escribir y como aplicar estos conocimientos a situaciones reales para ayudarnos en nuestro día a día. Bueno, sin más preámbulos vamos a lo que nos compete.

En esta ocasión veremos los Paneles, los paneles son películas SWF que almacenamos en las siguientes rutas respectivamente en función del sistema operativo:

  • Windows® VistaTM:

unidad de arranque\Users\nombre de usuario\Local Settings\Application Data\Adobe\Flash CS4\idioma\Configuration\WindowSWF

  • Windows XP:

unidad de arranque\Documents and Settings\nombre de usuario\Local Settings\Application Data\Adobe\Flash CS4\idioma\Configuration\WindowSWF

  • Mac OS® X:

Macintosh HD/Usuarios/nombre de usuario/Librería/Application Support/Adobe/Flash CS4/idioma/Configuration/WindowSWF

El acceso a estos paneles lo hacemos a través del menú Ventana -> Otros paneles, aquí encontraremos todos los Paneles que creemos dentro del directorio WindowSWF.

¿Para que sirven los paneles? y ¿Qué podemos hacer con un panel?

Bueno, básicamente podemos hacer todo lo que hacen los comandos, pero con la ventaja de tenerlo siempre abierto.

¿Y eso que quiere decir?

Pues que por ejemplo para ejecutar un comando tenemos que hacerlo a través del menú Comandos, con lo cual perdemos el área de trabajo, esto si utilizamos un comando basado en interfaz gráfica, pero si lo hacemos con un comando sencillo no tenemos forma de configurar parámetros con lo que perdemos más valor. Sin embargo con un Panel tenemos siempre visible el área de trabajo, tenemos acceso a toda la configuración que deseemos implementar en el panel y además podemos crear previews del resultado puesto que el panel es una película swf en la que podemos hacer tanto como deseemos.

A ver, a ver, ¿dices que los Paneles son películas SWF?

Así es, esta es la parte más poderosa de los Paneles, que son películas SWF, con lo cual las podemos crear con lo que más cómodos nos sintamos, por ejemplo con Flex, con Flash, con mtasc, todos estos los he probado y funcionan perfectamente, seguro que también se puede con HAXE aunque no lo he probado.

¿Y donde está el truco?

Bueno, realmente no es truco, pero bueno la magia que nos permite hacer esto es una función muy sencilla que lleva mucho tiempo ahí y que es más potente de lo que ha simple vista parece, la función que nos permite utilizar a nuestros queridos SWF’s como interfaz de los Paneles es la función MMExecute, a ésta función le tenemos que pasar como parámetro código JSFL y listo.

NOTA del escritor, osea yo, jejejeje
Una buena práctica es el encapsulamiento y además conseguir que nuestro Panel tenga poco acoplamiento. Esto es más sencillo de lo que suena, simplemente quiere decir que separemos el código AS y el código JSFL.

PARTE ActionScript, lógica de la vista del Panel

Bueno y ahora si por fin después de esta introducción ya podemos hablar sobre la forma en la que vamos a poner en práctica lo aprendido (pero que dice este tío, si lo único que hemos visto es la función MMExecute y una ruta rara) . Vamos a crear un Panel que nos ayude a crear tableros de ajedrez, si esos bellos tableros que se componen de 64 casillas, 8 filas y 8 columnas, alternando dos tipos de casillas.

Recuerdo que hace tiempo tomé un taller sobre ActionScript avanzado en el Flash For México 2004 que impartió Fernando Flores, ahí antes de empezar a picar código nos dijo una cosa que siempre recordaré y que sigo aplicando a diario en mis proyectos, la lista de la compra, o sea lo que queremos, lo que necesitamos de nuestra aplicación. En este caso que es lo que queremos que tenga este Panel, bueno, pues mi lista de la compra para este Panel es la siguiente:

  • Definir el tamaño de las casillas.
  • Definir el color de las casillas.
  • Tener un preview antes de crearlo.

Esta lista de la compra nos ayuda a saber que necesitaremos 2 instancias del Componente ColorPicker, una instancia del Componente NumericStepper y para ejecutar acciones el buen amigo Button. Con ellos tendremos la lógica de AS que nos ayudará a conseguir los valores necesarios para crear nuestro tablero.

Una vez que conseguimos los valores necesario hacemos la llamada al fichero JSFL encargado de crear el tablero, la llamada a este fichero es realmente la clave de éste Panel. El código es el siguiente:

MMExecute('fl.runScript( fl.configURI + "WindowSWF/JavaScript/Tablero.jsfl", "createBoard", ' + this.comColor1.selectedColor + ', ' + this.comColor2.selectedColor + ', ' + this.comNumericStepperSize.value + ' );');

La explicación de ese trozo de código es la siguiente:

MMExecute, esta función recibe como parámetro el código JSFL que deseamos ejecutar.

fl.runScript, esté método de sirve para ejecutar scripts con código JSFL. Recibe un parámetro obligatorio y dos opcionales, que en nuestro caso utilizamos.

  • El primero es la ruta del fichero JSFL que se desea ejecutar.
  • El segundo es el nombre de la función que se desea ejecutar dentro del fichero JSFL.
  • El tercero son los parámetros que enviamos a la función.

fl.configURI, esta propiedad nos devuelve la ruta de la carpeta configuration de Flash del equipo.

Hasta ahora lo único que hemos hecha ha sido simplemente llamar a un fichero JSFL alojado en la carpeta configuration/WindowSWF/JavaScript/Tablero.jsfl, hemos indicado que deseamos ejecutar la función createBoard dentro de este fichero y le hemos pasado los parámetros necesarios (Color1, Color2 y Tamaño).

Y ya está, nuestro Panel es así de simple, podemos hacer todo lo que nos venga en gana para hacerlo más bonito, con animaciones, diseños y demás, pero lo mínimo necesario para funcionar es lo que hemos hecho hasta ahora. Bueno, ahora si empieza la parte interesante que es la que desde el principio quiero explicar, lo que es realmente código JSFL y es el encargado de crear el tablero de Ajedrez. ¿Preparados? … Pues vamos allá.

Pero antes una imagen que como queda nuestra interfaz:

Panel Tablero

PARTE JSFL, lógica de … algo que no es la vista del Panel

Llegamos a este punto con una parte muy importante ya definida y es la función a la que se llama desde ActionScript con la función MMExecute, si, así es, me refiero a la función createBoard, pero no sólo sabemos que tenemos que crear esa función, también sabemos que recibe tres parámetros, con lo cual ya nos hacemos a la idea de algunas tareas que tendremos que hacer. Pero bueno, vamos a pensarlo un poco más para ver que elementos necesitaremos, teniendo en cuenta que el tablero sea fácil de usar y modificar.
Bueno, pues partiendo de estas premisas y pensando lo más fácil posible, planteo la creación de tres MovieClip’s.

  1. Caja 1, que será un cuadrado de las dimensiones y el color indicados por parámetro.
  2. Caja 2, que es lo mismo que la caja 1 pero con el otro color.
  3. Tablero, éste tendrá 32 instancias de cada Caja para formar el tablero.

Bueno, ahora si con las cosas claras es más fácil programar, entonces vamos por partes, hemos dicho que necesitamos crear MovieClip’s, esto es muy sencillo, para hacerlo necesitamos utilizar el método addNewItem del Objeto library, éste método recibe dos parámetros, el tipo de Item y el nombre del mismo. A continuación un ejemplo:

fl.getDocumentDOM().library.addNewItem("movie clip", "nombre del MovieClip");

Luego necesitamos editar el MovieClip creado en el paso anterior, esto lo hacemos con el método editItem del Objeto library, éste método recibe como parámetro el nombre del Item que deseamos editar. A continuación un ejemplo:

fl.getDocumentDOM().library.editItem("nombre del MovieClip");

Ahora dentro del MovieClip antes de dibujar el cuadro debemos definir el color, esto lo hacemos con el método setCustomFill del Objeto Document, éste método recibe un objeto como parámetro, donde indicamos el color y el estilo de relleno. A continuación un ejemplo:

fl.getDocumentDOM().setCustomFill( {color:_nColor, style:"solid"} );

Una vez que hemos definido el color del cuadro ya podemos dibujarlo, esto lo hacemos con el método addNewRectangle del Objeto Document, éste método recibe dos parámetros, un objeto con la posición y las dimensiones del rectángulo que crearemos y el factor de redondeo de las esquinas del mismo. A continuación un ejemplo:

fl.getDocumentDOM().addNewRectangle( { left:0, top:0, right:Tamaño, bottom:Tamaño }, 0);

Listo, con estos pasos hemos conseguido crear un MovieClip, editarlo, definir un color de relleno y dibujar un cuadro, ahora simplemente tenemos que salir del modo edición de éste MovieClip, esto lo hacemos con el método exitEditMode del Objeto Document. A continuación un ejemplo:

fl.getDocumentDOM().exitEditMode();

Repetimos estos pasos y conseguiremos crear el segundo cuadro.

NOTA
Una buena práctica es encapsular estos pasos en una función para reutilizarla en más ocasiones.

Bueno, con esto ya tenemos dos MovieClip’s en la biblioteca, del tamaño y color deseados, ahora nos queda montar el tablero. Para esto necesitaremos crear otro MovieClip e instanciar 64 Items de la biblioteca, 32 de un color y 32 de otro. Esto lo conseguiremos con el siguiente código,:

fl.getDocumentDOM().library.addNewItem("movie clip", "tablero");
fl.getDocumentDOM().library.editItem("tablero");
var n = 0;
for (var i = 1; i <= 8; i++)
{
    for (var j = 1; j <= 8; j++)
    {
        var sItemName = (n % 2 == 0) ? "casilla1" : "casilla2";
        fl.getDocumentDOM().library.addItemToDocument({x:(j - 1) * _nSize, y:(i - 1) * _nSize}, sItemName);
        n++;
    }
    n++;
}
fl.getDocumentDOM().exitEditMode();

De ese código la parte nueva que vemos de JSFL es el método addItemToDocument, del Objeto library, éste método nos permite instanciar elementos de la biblioteca en el escenario, recibe dos parámetros, el primero es un objeto con las coordenadas X e Y en las que deseamos instanciar el Item y el segundo es una cadena con el nombre del Item que deseamos instanciar.

Y listo, eso ha sido todo, quizá contado trozo a trozo no tenga mucho sentido, pero mi intención era explicar cada uno de los método utilizados. A continuación pongo el código JSFL completo://Declaración de variables

var oDoc;
var oLib;
var sBoxName1 = "box_1";
var sBoxName2 = "box_2";
var sBoardName = "board";

/**
* @method	createBoard
* Método encargado de crear un tablero.
* @param	_nColor1	Number		Número que indica el color primario del tablero
* @param	_nColor2	Number		Número que indica el color secundario del tablero
* @param	_nSize		Number		Número que indica el tamaño de las casillas
* @return	Void
*/
function createBoard(_nColor1, _nColor2, _nSize)
{
    if (this.config())
    {
        //Lamada al método createBox para crear MovieClp's
        this.createBox(this.sBoxName1, _nSize, _nColor1);
        this.createBox(this.sBoxName2, _nSize, _nColor2);

        //Hacemos una comprobación, si existen el item en la biblioteca lo eliminamos.
        if (this.oLib.itemExists(this.sBoardName))	this.oLib.deleteItem(this.sBoardName);

        //Creamos y editamos el MovieClip tablero
        this.oLib.addNewItem("movie clip", this.sBoardName);
        this.oLib.editItem(this.sBoardName);
        var n = 0;
        for (var i = 1; i <= 8; i++)
        {
            for (var j = 1; j <= 8; j++)
            {
                var sItemName = (n % 2 == 0) ? this.sBoxName1 : this.sBoxName2;
                //Añadimos al MovieClip una instancia de la casilla en su posición correspondiente
                this.oLib.addItemToDocument({x:(j - 1) * _nSize, y:(i - 1) * _nSize}, sItemName);
                n++;
            }
            n++;
        }

        //Salimos del modo de edición y volvemos al escenario
        this.oDoc.exitEditMode();
    }
}

/**
* @method	createBox
* Método encargado de crear un Item de tipo MovieClip en la biblioteca, editarlo y dentro crear un cuadro de tamaño y color indicados por parámetro.
* @param	_sName		String		Cadena que indica el nombre del Item que se creará en la biblioteca.
* @param	_nSize		Number		Número que indica el tamaño del cuadro que se creará.
* @param	_nColor		Number		Número que indica el color del cuadro que se creará.
* @return	Void
*/
function createBox(_sName, _nSize, _nColor)
{
    //Hacemos una comprobación, si existen el item en la biblioteca lo eliminamos.
    if (this.oLib.itemExists(_sName))	this.oLib.deleteItem(_sName);

    //Añadimos y editamos el MovieClip
    this.oLib.addNewItem("movie clip", _sName);
    this.oLib.editItem(_sName);
    //Definimos el color y estilo del trazo
    this.oDoc.setCustomStroke( {color:"#000000", thickness:1} );
    //Definimos el color y estilo de relleno del cuadro
    this.oDoc.setCustomFill( {color:_nColor, style:"solid"} );
    //Dibujamos el cuadro
    this.oDoc.addNewRectangle( { left:0, top:0, right:_nSize, bottom:_nSize }, 0);
    //Salimos del modo de edición y volvemos al escenario
    this.oDoc.exitEditMode();
}

/**
* @method	config
* Método encargado de la configuración del JSFL
* @return	Void
*/
function config()
{
    fl.showIdleMessage(false);
    fl.outputPanel.clear();

    var ret = false;

    if(fl.getDocumentDOM())
    {
        //Obtenemos y configuramos las referencias al Documento y a la Biblioteca
        this.oDoc = fl.getDocumentDOM();
        this.oLib = this.oDoc.library;
        ret = true;
    }
    else
    {
        alert("Debes tener un documento abierto.");
    }

    return ret;
}

Aquí se pueden descargar los ficheros de este tutorial. Cualquier, duda, sugerencia o comentario, aquí estaré.

Entradas relacionadas:

Get Adobe Flash playerPlugin by wpburn.com wordpress themes