El prototipado es un mecanismo que permite la especificación
de nuevos tipos de nodos definidos por el usuario. Esto además
permite la encapsulación y parametrización de figuras
geométricas, comportamientos o ambos.
Una definición de prototipos consiste de lo siguiente:
Entonces una definición de prototipo sería:
PROTO nombre_del_prototipo[eventIn nombre_del_tipo_de_evento nombre
eventOut nombre_del_tipo_de_evento nombre
exposedField nombre_del_tipo_de_campo nombre default valor
field nombre_del_tipo_de_campo nombre default valor
]{
cero o más escenas gráficas.
(nodos, prototipos y rutas, conteniendo IS)
}
Un prototipo no define un nodo dentro de una escena gráfica,
lo que hace es crear un nuevo tipo de nodo (nombrado por el nombre_del_prototipo)
que puede ser creado posteriormente en el mismo archivo como si
fuera un nodo ya incorporado.
La primera escena gráfica, (referenciada como la escena
gráfica primaria), encontrada en la definición de
prototipo, conteniendo la palabra IS es usada para representar
al nodo. Las otras escenas gráficas no son renderadas,
pero pueden ser referenciadas via rutas o scripts y de ese modo
no ser ignoradas.
Tanto las declaraciones de PROTO como de EXTERNPROTO pueden aparecer
en cualquier declaración de ROUTE.
Las declaraciones eventIn y eventOut exportan eventos desde la escena gráfica primaria. Especificando cada tipo de evento tanto en la declaración de prototipo como en la escena gráfica primaria se pretende prevenir errores y tener consistencia con los prototipos externos.
Los eventos generados y recibidos por los nodos en la implementación
de los prototipos son asociados con el prototipo usando la palabra
reservada IS. Por ejemplo la siguiente declaración pone
un nodo Transform incorporado en un evento set_translation dándole
a éste un nuevo nombre (set_position) en la interface del
prototipo.
PROTO FooTransform [eventIn SFVec3f set_position]{
Transform {set_translation IS set_position}
}
Si permitimos a un prototipo que exporte campos, permitimos que
el estado inicial de un objeto prototipado sea especificado cuando
una instancia del objeto es creada. Los campos del prototipo son
asociados con campos en la implementación usando la palabra
reservada IS. Por ejemplo:
PROTO BarTransform[exposedField SFVec3f position]{
Transform {translation IS position}
}
La declaración IS puede aparecer dentro de los nodos, donde
sea que los campos puedan aparecer. Especificando una declaración
IS para un nodo en la escena gráfica primaria, la cual
no es parte de la implementación de un prototipo, constituye
un error.
Un prototipo es instanciado como si fuera un nombre_de_tipo en
un nodo incorporado. El nombre del prototipo debe ser único
dentro del alcance del archivo. Un nodo ya incorporado y un prototipo
no pueden ser renombrados.
Las instancias de los prototipos pueden ser nombradas usando DEF
y pueden ser múltiplemente instanciadas usando USE como
cualquier nodo incorporado. Una instancia de un prototipo puede
ser usada en la escena gráfica donde sea que el primer
nodo de la escena primaria gráfica pueda ser usada. Por
ejemplo un prototipo definido como:
PROTO MyObject [...]{
Box{...}
ROUTE ...
Script{...}
...
}
puede ser instanciado donde sea que Box pueda ser usado, puesto
que el primer nodo de la escena del prototipo primario en la escena
gráfica es un nodo Box.
Una escena gráfica de un prototipo define unos DEF/USE
separados del resto de la escena; nodos DEFinidos dentro de un
prototipo no pueden ser USEados fuera del alcance del prototipo,
y nodos DEFinidos fuera del alcance del prototipo no pueden ser
USEados dentro del alcance del prototipo.
Un prototipo puede ser instanciado en un archivo en cualquier lugar, después de haber completado la definición de éste. Un prototipo no puede ser instanciado dentro de su implementación (los prototipos recursivos son ilegales). El siguiente ejemplo produce un error.
PROTO Foo[]{
Foo{}
}
La sintaxis para la definición de prototipos en archivos
externos es la siguiente:
EXTERNPROTO nombre_del_prototipo[eventIn nombre_del_tipo_de_evento nombre
eventOut nombre_del_tipo_de_evento nombre
field nombre_del_tipo_de_campo
...]
"URL" o ["URL", "URL", ... ]
Se produce un error cuando las declaraciones de eventIn/eventOut
en el EXTERNPROTO no son un subconjunto de las declaraciones eventIn/eventOut
especificadas en la declaración de PROTO referenciada por
el URL. Si múltiples URLs o URNs son especificados, el
browser busca en orden de preferencia.
A diferencia de los prototipos, un prototipo externo no contiene
una implementación del tipo de nodo, en vez de eso la implementación
del prototipo es traída desde una URL o URN. La otra diferencia
entre un prototipo y un prototipo externo es que estos últimos
no contienen valores por defecto para los campos. El prototipo
externo referencia un archivo que contiene la implementación
del prototipo, y ese archivo contiene los valores por defecto
de los campos.
Se permite la creación de bibliotecas, con definiciones
de PROTO reusables, los browsers pueden reconocer URLs de EXTERNPROTO
que finalicen con "#nombre#, con "nombre" indicando
el nombre del prototipo en el archivo. Por ejemplo, una biblioteca
de materiales estándar pueden ser guardados en un archivo
llamado "materiales.wrl", como sigue:
#VRML V2.0 utf8
PROTO Gold [] {Material {...}}
PROTO Silver [] {Material {...}}
... etc
Un Material desde esta biblioteca puede ser entonces referenciado
y usado como sigue:
#VRML V2.0 utf8
EXTERNPROTO Gold [] "http://.../materiales.wrl#Gold"
...
Shape{appearance Appearance{material Gold{}}
geometry ...
}
La ventaja de esto es que sólo se necesita referenciar
una URL para tener las diversas cosas a usar desde la biblioteca;
la desventaja es que la biblioteca completa debe ser transmitida
a través de la red, siendo que es probable que sólo
usemos un prototipo en el archivo.