Hello, Avatar!

Second Life et Programmation Créative

Aller au contenu | Aller au menu | Aller à la recherche

Utilisez le Whiteboard sur votre OpenSim !

Nous avons vu dans un billet précédent qu'il est possible de dessiner sur une primitive à l'aide d'une applet écrit en Silverlight.

Chose promise, chose dûe : nous allons voir comment utiliser ce dernier sur votre OpenSim, sans toucher autre chose qu'un paramètre et une ligne dans un petit script en LSL.

Tout d'abord, il faut activer le XMLRPC sur votre simulateur afin que les scripts LSL puissent avoir des oreilles : pour ce faire, renseignez le paramètre remoteDataPort avec le port de votre choix.

Par exemple :

; Uncomment below to enable llRemoteData/remote channels
remoteDataPort = 80

Bien entendu, il faudra rendre visible ce port de l'extérieur en ajustant les paramètres de votre pare-feu.

Voila qui est fait. A présent, prenez le script ci dessous dans un éditeur. Changez le paramètre TargetSimURL en lui mettant l'adresse publique de votre sim, puis collez tout dans le contenu d'un prim.

// Mettre ci dessous l'adresse ou est hebergee la page. Ne changer que si vous l'hebergez vous-meme
string WhiteBoardURL="http://lslblog.free.fr/draw/";

// Mettre l'adresse IP, ou l'URL de votre sim, suivie du port utilise par RemoteData
string TargeSimURL = "http://maupiti.ath.cx";

// Exemples:
// http://maupiti.ath.cx (80 par défaut)
// http://127.0.0.1:8080

key remoteChannel;
string name = "";

default
{
    state_entry()
    {
        llSetText("Touchez le prim pour dessiner dessus !", <1,1,0>, 1);
        llOpenRemoteDataChannel();
    }
   
    on_rez()
    {
        llResetScript();
    }

    touch_start(integer c)
    {
        name = llDetectedName(0);
        llSetText("Hello " + name + ", allez à l'URL indiquee dans le Chat, puis dessinez !", <1,1,0>, 1);

        llInstantMessage(llDetectedKey(0),
            "Allez sur\n " + WhiteBoardURL + "?key=" +
            remoteChannel + "&tgt=" + TargeSimURL +
            " \navec votre navigateur externe pour dessiner sur ce prim ! ^^");
    }

    remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
    {
        if (type == REMOTE_DATA_CHANNEL)
        {
            remoteChannel = channel;
        }

        if (type == REMOTE_DATA_REQUEST)
        {
            llSetText(name + "\nTouchez le prim pour dessiner dessus !", <1,1,0>, 1);
            llRemoteDataReply(channel, NULL_KEY, "__OK__", 0);
            osSetDynamicTextureData("", "vector", sval, "512", 0);
        }
    }  
}

Voilà, en principe, ça marche !

A l'attention de ceux qui souhaitent héberger la chose eux-même, j'ai joint à ce billet un fichier zip qui contient :

  • Une petite partie Web : une page HTML, le fichier XAP pour Silverlight et un petit proxy écrit en PHP;
  • Le code source de l'application en Silverlight sous la forme d'un projet Visual Studio 2008.

Il reste encore quelques aménagements à apporter, comme par exemple pouvoir utiliser la forme executable du plugin (le XAP) sur n'importe quel site. Ce qui pour le moment n'est pas possible sans modifier une petite ligne dans l'application Silverlight.

Bon amusement !

Un Whiteboard pour OpenSim avec Silverlight

Connaissez-vous Silverlight ? C'est l'équivalent d'Adobe Flash, mais côté Microsoft.

Avec Silverlight, je peut développer en C#, tirant ainsi les bénéfices de mon expérience acquise en .NET sans investissement coûteux en terme d'apprentissage. Oui, d'accord, Silverlight est encore en version bêta, mais il est vraiment très stable et la version finale pleine de promesses est prévue pour la fin de cette année.

Silverlight est destiné à tourner sur tous les navigateurs, toutes les plateformes (Mac) ainsi que sous Linux, ou son équivalent OpenSource répond au doux nom de MoonLight.

Mais bon, le but de l'article n'est pas de faire de la publicité pour Silverlight, mais plutôt de vous montrer ce qu'on peut en faire avec OpenSim. Aussi, j'ai réalisé un tableau blanc pour dessiner sur un prim à main levée à partir du Web. Un genre de tableau blanc qui pourrait servir lors de conférence, par exemple.

Pour s'en servir, rien de plus facile, voyez plutôt :

Whiteboard0
Tout d'abord, on avise le prim, tout blanc, et on clique dessus. Ca nous donne un lien vers une page Web qu'il faut ouvrir à l'aide d'un navigateur externe.

whiteboard1 
Ceci fait, on dessine à l'aide de l'application en Silverlight, dans sa page Web... et on clique sur Envoyer.

Whiteboard2 
Et normalement, si tout se passe bien, la texture apparait sur les faces du prim.

Whiteboard3

Et il est possible d'avoir plusieurs whiteboards sur une même parcelle. Ce qui est aujourd'hui impossible sur la grille des Linden, du fait qu'une page Web ou une image externe est considée comme un média, et qu'on ne peut en mettre que un sur une parcelle...

Ceci est rendu possible grâce au XMLRPC récemment réparé, qui me permet de transmettre des instructions vectorielles à un script écrit en C#, tournant dans chaque primitives. On imagine alors les possibilités de l'exterieur, comme du build d'un batiment en tracant les contours, de sculpties crées et importées directement...

[Update 02/07/2008]
Le code source est disponible au téléchargement ici : http://lslblog.free.fr/index.php/post/2008/06/02/Utilisez-le-Whiteboard-sur-votre-OpenSim

XMLRPC sur OpenSim : osOpenRemoteDataChannel(key channelID)

Juste un petit post pour faire part d'une nouveaute sympathique dans la gestion du XMLRPC avec OpenSim et remote_data, maintenant qu'il est repare.

Comme les scripteurs le savent bien, pour transformer un script en serveur XMLRPC, il faut ouvrir un canal a l'aide de llOpenRemoteDataChannel. Ensuite, cette instruction provoque un evenement remote_data, qui, la premiere fois, transmet une key qui correspond au numero de canal.

Cette cle devra etre transmise a chaque appel. Aussi, comme au depart la key n'est connue que par le script LSL, il faut monter toute une tringlerie pour que cette key soit recuperee par le client d'une maniere ou d'une autre. Pour des raisons de securite, c'est tout a fait adapte, mais pour des prototypages d'applications simples et rapides, c'est vraiment pas le pied.

C'est pourquoi je me suis attele a creer la fonction osOpenRemoteDataChannel(key channelID) qui accueille en parametre un numero de canal de type UUID. Cela permet d'avoir une "cle publique" pouvant etre incorporee directement a un client, et de prototyper ainsi une ebauche d'echange de donnees de facon rapide.

Finis alors les llOwnerSay((string) channel), les copier/coller entre le viewer et son outil de developpement, recommencer en cas de redemarrage du script ou du simulateur et j'en passe.

Un grand merci aux membres de la core team d'OpenSim pour avoir integre ces modifs au trunk aussi rapidement.

Du XMLRPC avec OpenSim

Le XMLRPC avec remote_data vient de faire son arrivee sur OpenSim !

Pour l'utiliser, il faudra positionner le parametre remoteDataPort dans le fichier OpenSim.ini en lui donnant un numero de port.

Dans OpenSim.ini.example, on trouve :

remoteDataPort = 20800

Si le service XMLRPC que vous souhaitez implementer en LSL doit etre visible de l'exterieur, il vous faudra ouvrir le port correspondant. Pour ma part, j'utilise plutot le port 80, car mon hebergeur Web (free) bride les appels externes autres que sur certains ports.

Ensuite, vous pourrez faire un essai en prenant le script ci-dessous, qui est tire de ce tutorial, mais avec une petite variante toutefois : parce qu' un bug encore non corrige existe avec l'evenement state_exit() qui se declenche avant le state_entry(), j'ai du retirer cet evenements de l'exemple pour que ca marche.

key remoteChannel;
init()
{
    llOpenRemoteDataChannel(); // create an XML-RPC channel
}

default
{
    state_entry()
    {
        init();
    }

    on_rez(integer param)
    {
        llResetScript();        
    }

    remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
    {
         if (type == REMOTE_DATA_CHANNEL)
        { // channel created
            llSay(DEBUG_CHANNEL,"Channel opened for REMOTE_DATA_CHANNEL" +
                (string)channel + " " + (string)message_id + " " + (string)sender + " " +                        
                (string)ival + " " + (string)sval);
             remoteChannel = channel;
             llOwnerSay("Ready to receive requests on channel \"" + (string)channel + "\"");                        
             state receiving; // start handling requests
        }
        else
        {
            llSay(DEBUG_CHANNEL,"Unexpected event type");
        }
     }
}

state receiving
{
    state_entry()
    {
        llOwnerSay("Ready to receive information from outside SL");
    }
 
     on_rez(integer param)
    {
        llResetScript();
    }

    remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
    {
        if (type == REMOTE_DATA_REQUEST)
        {
            // handle requests sent to us
            llSay(DEBUG_CHANNEL,"Request received for REMOTE_DATA_REQUEST " + (string)channel + " " +
                (string)message_id + " " + (string)sender + " " + (string)ival + " " + (string)sval);
                llRemoteDataReply(channel,NULL_KEY,"I got it",2008);
                llOwnerSay("I just received data in "+ llGetRegionName() +
                " at position " + (string)llGetPos() + "\n" +
                "The string was " +  sval + "\nThe number was " + (string)ival + ".");
        }
    }
}

Voila, il vous suffit de glisser ce bout de code dans un primitive, puis de noter la cle qu'il vous communique afin de l'integrer au programme client.

C'est cette cle qu'il va falloir fournir lors de chaque appel au service XMLRPC. Ce qui veut dire que si vous redemarrez le script, la cle sera differente, et il vous faudra la modifier a nouveau dans le programme client.
C'est pourquoi certains scripts evolues font au prealable une sorte d'echange de cles afin de pouvoir fonctionner ensemble. C'est tres lourd.

Aussi, mon prochain travail consistera a creer une instruction LSL specifique a OpenSim pour preciser la cle qui sera utilisee par le script en LSL. Je pense a un truc du genre osOpenRemoteDataChannel(key channel), ce qui evitera la torture decrite ci-dessus.

Pour ce qui est du programme client, celui en PHP qu'on trouve sur cette page fonctionne tres bien, et pour ma part un petit truc en C# de 5 lignes a bien fonctionne egalement.

Quant aux les contraintes connues sur la "grille officielle" avec XMLRPC (delais entre deux appels et autres limitations que j'ai oublie...), elles ne sont pas applicables ici. De plus, les temps d'execution sont bien plus rapides, de l'ordre de l'instantane. Ca n'est pas etonnant, quand on pense a la charge de tels serveurs chez Linden Labs...

Voila, maintenant qu'OpenSim a des oreilles in-world, alors profitez-en !