#VRML V2.0 utf8
WorldInfo
{
title "Copyright (C) 2002 by Herbert Stocker (AKA hersto)"
info
[
" The original versions of the PROTO TextureTextLine was written
by me, Herbert Stocker.
The original versions and some test and demonstration Worlds can
be found at http://www.hersto.de/ .
"
" You can use and modify the PROTO in this file if you keep the credit
information valid and if you don't remove the link to the originating
site http://www.hersto.de/ .
In brief, keep this WorldInfo node along with the Proto.
"
" Please send a message to hersto@hersto.de where you describe how you
use or improved the nodes. Especially if you included the improved
versions.
"
]
}
#
#EXTERNPROTO TextureTextLine
#[
# exposedField SFString text # ""
# exposedField SFVec2f size # .7 1
# exposedField SFString allign # "LEFT" # or "CENTER" or "RIGHT"
#
# field SFBool singleSided # TRUE # Would prefer an SFBool twoSided, but type conversion or semantics conversion cannot be performed with the IS statement.
#
# # configuration parameters that describe the font texture
# field SFFloat baseLine # .2 # multiplied with size.y this is the distance of the base line to the bottom of letters like g, p, q, etc.
#
# field SFInt32 firstChar # 32 # utf8 code of it. (Ok, only ascii code is supported for the text field).
# field SFInt32 numCharsHorz # 16
# field SFInt32 numCharsVert # 14
#
# field SFInt32 imageWidth # 512
# field SFInt32 imageHeight # 448
#
#
# eventOut SFBool isLoaded
#]
# "TextureTextLine.wrl#TextureTextLine"
#
PROTO TextureTextLine
[
exposedField SFString text ""
exposedField SFVec2f size .7 1
exposedField SFString allign "LEFT" # or "CENTER" or "RIGHT"
field SFBool singleSided TRUE # Would prefer an SFBool twoSided, but type conversion or semantics conversion cannot be performed with the IS statement.
# configuration parameters that describe the font texture # TBD: should be moved to an external PROTO similar to the FontStyle node.
field SFFloat baseLine .2 # multiplied with size.y this is the distance of the base line to the bottom of letters like g, p, q, etc.
field SFInt32 firstChar 32 # utf8 code of it. (Ok, it's ascii code).
field SFInt32 numCharsHorz 16
field SFInt32 numCharsVert 14
field SFInt32 imageWidth 512
field SFInt32 imageHeight 448
eventOut SFBool isLoaded
field MFString credits "Initial idea and copyright by Herbert Stocker, http://www.hersto.com/"
]
{
DEF IFS IndexedFaceSet
{
coord DEF Coord Coordinate
{
}
texCoord DEF TexCoord TextureCoordinate
{
}
solid IS singleSided
}
PROTO EFFS
[
exposedField SFString text ""
exposedField SFVec2f size .7 1
exposedField SFString allign "LEFT"
]
{ Group {} }
DEF EFFS EFFS
{
text IS text
size IS size
allign IS allign
}
DEF Worker Script
{
#interface
field SFNode effs USE EFFS
eventIn SFString set_text
eventIn SFVec2f set_size
eventIn SFString set_allign
eventOut MFVec3f coord_changed
eventOut MFInt32 coordIdx_changed
eventOut MFVec2f texCoord_changed
eventOut MFInt32 textCoordIdx_changed
eventOut SFBool solid_changed
#config
# TBD: these #config parameters should be specifyable on the PROTO interface.
field SFFloat baseLine IS baseLine
field SFInt32 firstChar IS firstChar
field SFInt32 numCharsHorz IS numCharsHorz
field SFInt32 numCharsVert IS numCharsVert
field SFInt32 imageWidth IS imageWidth
field SFInt32 imageHeight IS imageHeight
#internal
field SFString text ""
field SFVec2f size .7 1
field SFInt32 allign 0 # = cAllignLeft
field SFBool haveNewText FALSE
field SFBool haveNewSize FALSE
field SFBool haveNewAllign FALSE
field SFInt32 cAllignLeft 0
field SFInt32 cAllignCenter 1
field SFInt32 cAllignRight 2
field SFBool IsCosmo FALSE
field SFInt32 PixelPerCharHorz 0
field SFInt32 PixelPerCharVert 0
url "vrmlscript:
// Is there any function that returns the utf8 value of a character?
// Could be usefull now.
// Since I don't know of any, I'm doing it on my own.
// And since utf8 is such a large range, we do it only for extended ascii,
// i.e. for values from 32 to 255. I.e. for one of the old character setst that
// were in use before utf8 (unicode) came.
function ascii(ch)
{
if(IsCosmo)
{
// Cosmo even can't compare two strings. ARGH!
// Why is the specification of the VRML standard (and VrmlScript) so incomplete! AARRGGHH!
// So we have to do linear search. What kind of software design is this!!!
for(var C= 32; C<256; C++ )
{
if(ch == chr(C))
return C;
}
}
// we do successive approximation:
var Min= 0;
var Max= 256;
while(Max - Min > 1)
{
var Mid= Math.floor((Min + Max) / 2);
if(ch < chr(Mid))
Max= Mid;
else
Min= Mid;
}
return Min;
}
function chr(asc)
{
return ascii2Char[Math.floor(asc / 16)].charAt(asc % 16);
}
function Update()
{
if(haveNewText || haveNewSize || haveNewAllign)
{
var Shift= allign == cAllignLeft? 0 :(
allign == cAllignCenter? text.length / 2 :(
allign == cAllignRight? text.length :
0 ));
var BottomY= baseLine * -size.y;
var TopY= (1 - baseLine) * size.y;
var Coord= new MFVec3f;
Coord.length= text.length * 2 + 2;
for(var CharNo= 0; CharNo<=text.length; CharNo++ )
{
Coord[CharNo * 2 + 0].x= (CharNo - Shift) * size.x;
Coord[CharNo * 2 + 0].y= TopY;
Coord[CharNo * 2 + 1].x= Coord[CharNo * 2 + 0].x;
Coord[CharNo * 2 + 1].y= BottomY;
}
coord_changed= Coord;
}
if(haveNewText)
{
var CoordIdx= new MFInt32;
CoordIdx.length= text.length * 5;
// write only the left two edges of each letter to Coord. (The right ones are the left ones of the next character, of course)
for(var CharNo= 0; CharNo<text.length; CharNo++ )
{
// Also create a face for each letter.
CoordIdx[CharNo * 5 + 0]= CharNo * 2 + 0;
CoordIdx[CharNo * 5 + 1]= CharNo * 2 + 1;
CoordIdx[CharNo * 5 + 2]= CharNo * 2 + 3;
CoordIdx[CharNo * 5 + 3]= CharNo * 2 + 2;
CoordIdx[CharNo * 5 + 4]= -1;
}
coordIdx_changed= CoordIdx;
// Now do the texture coords:
var Coord= new MFVec2f;
Coord.length= text.length * 4;
// We reuse CoordIdx, because it has already the correct length
// and because it already has the -1 values at the proper positions.
for(var CharNo= 0; CharNo<text.length; CharNo++ )
{
var asc= ascii(text.charAt(CharNo));
var TopLeft= new SFVec2f( ((asc - firstChar) % numCharsHorz) / numCharsHorz
, 1 - (Math.floor((asc - firstChar) / numCharsHorz) / numCharsVert)
);
// Top Left
Coord[CharNo * 4 + 0].x= TopLeft.x;
Coord[CharNo * 4 + 0].y= TopLeft.y;
// Bottom Left
Coord[CharNo * 4 + 1].x= TopLeft.x;
Coord[CharNo * 4 + 1].y= TopLeft.y - 1/numCharsVert;
// Top Right
Coord[CharNo * 4 + 2].x= TopLeft.x + 1/numCharsHorz;
Coord[CharNo * 4 + 2].y= TopLeft.y;
// Bottom Right
Coord[CharNo * 4 + 3].x= TopLeft.x + 1/numCharsHorz;
Coord[CharNo * 4 + 3].y= TopLeft.y - 1/numCharsVert;
CoordIdx[CharNo * 5 + 0]= CharNo * 4 + 0;
CoordIdx[CharNo * 5 + 1]= CharNo * 4 + 1;
CoordIdx[CharNo * 5 + 2]= CharNo * 4 + 3;
CoordIdx[CharNo * 5 + 3]= CharNo * 4 + 2;
}
texCoord_changed= Coord;
textCoordIdx_changed= CoordIdx;
}
}
function initialize()
{
IsCosmo= Browser.getName() == 'CosmoPlayer' // TBD: adjust this string to what Cosmo Player returns.
|| Browser.getName() == 'NexternetPlayer'
;
PixelPerCharHorz= imageWidth / numCharsHorz;
PixelPerCharVert= imageHeight / numCharsVert;
text= effs.text;
size= effs.size;
allign= effs.allign == 'LEFT'? cAllignLeft :(
effs.allign == 'CENTER'? cAllignCenter :(
effs.allign == 'RIGHT'? cAllignRight : cAllignLeft ));
// This is a workaround for old Contact versions:
// EXTERNPROTO initialization parameters seam to not work correctly.
if(!size.x && !size.y)
size= new SFVec2f(.7, 1);
oldSize= size;
oldAllign= allign;
haveNewText= true;
haveNewSize= true;
haveNewAllign= true;
Update();
}
function set_text(t)
{
text= t;
haveNewText= true;
}
function set_size(s)
{
size= s;
haveNewSize= true;
}
function set_allign(a)
{
allign= a == 'LEFT'? cAllignLeft :(
a == 'CENTER'? cAllignCenter :(
a == 'RIGHT'? cAllignRight : cAllignLeft ));
haveNewAllign= true;
}
function eventsProcessed()
{
Update();
}
"
# ... and since I don't know of a function that does the reverse,
# we have to keep a table for that. Hope it works. (and Hope no text editor mangles this literal.)
field MFString ascii2Char
[
" "
" "
" !\"#$%&'()*+,-./"
"0123456789:;<=>?"
"@ABCDEFGHIJKLMNO"
"PQRSTUVWXYZ[\]^_"
"`abcdefghijklmno"
"pqrstuvwxyz{|}~"
""
""
""
""
""
""
""
""
]
}
ROUTE EFFS.text TO Worker.set_text
ROUTE EFFS.size TO Worker.set_size
ROUTE EFFS.allign TO Worker.set_allign
ROUTE Worker.coord_changed TO Coord.point
ROUTE Worker.coordIdx_changed TO IFS.set_coordIndex
ROUTE Worker.texCoord_changed TO TexCoord.point
ROUTE Worker.textCoordIdx_changed TO IFS.set_texCoordIndex
# ROUTE Worker.solid_changed TO IFS.solid
DEF LastNode Script
{
eventOut SFBool isLoaded IS isLoaded
url "vrmlscript:
function initialize()
{
isLoaded= true;
}
"
}
}
Shape
{
appearance Appearance {
material Material {
diffuseColor .55 .09 .05
specularColor .29 .31 .05
emissiveColor .21 .03 .02
ambientIntensity .0267
shininess .19
}
texture ImageTexture
{
url "OCR-1.5.png"
}
}
geometry TextureTextLine
{
text "Hellow Orld!"
}
}
Shape
{
appearance Appearance {
material Material {
diffuseColor .02 .24 .53
specularColor .32 .4 .4
emissiveColor .01 .12 .27
ambientIntensity .0333
shininess .54
}
}
geometry Sphere
{
radius .1
}
}
NavigationInfo
{
type "EXAMINE"
}
|