[Concours GAGNÉ] Le schmillScript ;) concours de script sans script!

Répondre
Partager Rechercher
Bon, allez un indice ENORME

La texture s'appelle : 2x3p2_256_CarresFondNoirBordsNoirs

Evidemment, seul le début du nom est important:

"CarresFondNoirBordsNoirs"" pour me souvenir du look, car j'en ai plusieurs variantes.

"256" pour la taille de la texture

"2x3p2" pour ... ???


Ca va ptet faire bouger vos neurones pendant le déjeuner...
Citation :
Publié par Smile
Un écran pour visionner tes propres vidéos directement dans SL .

Je donne ma langue au chat , bon les scripteurs vous vous réveillez ....... je veux savoir moi .
Non, pas pour les vidéos, ça existe déjà depuis longtemps et quel rapport avec cette texture?

Te décourage pas Smile, vous êtes plusieurs à être très très proche du machin, toi y compris!
Je les vu ce nombre

est ce une résolution d'écran?

est ce un calcul?

est ce un écran noir?

est ce pour une sélection de scène? vu que c'est un écran
Citation :
Publié par milkcandy
Je les vu ce nombre

est ce une résolution d'écran?

est ce un calcul?

est ce un écran noir?

est ce pour une sélection de scène? vu que c'est un écran
Non, pas une résolution d'écran. un autre genre de résolution...
Non, pas un calcul
Non, pas un écran noir. Quoique dans le principe, avec cette texture, le fond est noir.
Citation :
Publié par cerise laville
c est donc un zoom sur un endroit de la texture comportant 3 lignes et 2 colonnes?
la postition des carres blancs dans cette zone donne une info?
c est pas du morse?
OUI, on zoome effectivement sur une zone de 3 lignes et 2 colonnes Super important ça...

Si ça donne une info, en quelque sorte oui.

Non ce n'est pas du morse.
Ta schmilltexture permet elle d afficher tous les motifs imaginables parce toutes les combinaisons de ractangles 3*2 avec des carrés blancs et noirs peuvent etre tretrouvés dans la schmilltexture , soit par zoom de textures , soit par déplacement de textures , par rotation de textures et combinaison de celles ci ?

Donc la scmillprim composée avec d autres scmillprims pourrait dessiner n importe quel contour ( eveidemment ca fait un peu "pixellisé"

Ainsi , de facon plus pratique , ta schmilltexture pourrait servir par exemple :
- a dessiner un peu à la mode pixel art
- pouvoir écrire des caractères de facon dynamique avec la fonte de police qu on veut ; ca peut etre compliqué et lourd en prims mais a l etat actuel on est obligé via xxyztext ( ou les dérivés ) de stocker une texture avec une fonte de police qui ne poourra pas etre changée
Citation :
Publié par redpurple
Ta schmilltexture permet elle d afficher tous les motifs imaginables parce toutes les combinaisons de ractangles 3*2 avec des carrés blancs et noirs peuvent etre tretrouvés dans la schmilltexture , soit par zoom , soit par déplacement, par rotation et combinaison de celles ci ?

Donc la scmillprim composée avec d autres scmillprims pourrait dessiner n importe quel contour ( eveidemment ca fait un peu "pixellisé"

Ainsi , de facon plus pratique , ta schmilltexture pourrait servir par exemple :
- a dessiner un peu à la mode pixel art
- pouvoir écrire des caractères de facon dynamique avec la fonte de police qu on veut ; ca peut etre compliqué et lourd en prims mais a l etat actuel on est obligé via xxyztext ( ou les dérivés ) de stocker une texture avec une fonte de police qui ne poourra pas etre changée
OUUUUIIIIIIIIIIII

Voici le vainqueur !!!

(plus de détails dans un post à venir...)
(je fais un post séparé, je voulais juste annoncer le vainqueur plus rapidement)

Bravo Redpurple !
Résultat des courses :

1er prix : Redpurple 1000 lindon$
2ème prix : MilkCandy 500 lindon$

(donnez moi vos noms d'avatars SL pour recevoir les sous)

Bon, un peu plus d'explications maintenant :

J'ai toujours été frustré de ne pas pouvoir dessiner dans SL, que ce soit par script, ou de façon interactive. On ne peut pas modifier les pixels d'une texture, sinon nos amis les lindons perdraient des sous sur les uploads...

L'objectif est donc de pouvoir contrôler des pixels pour afficher/dessiner des images.
Raisonnement n°1 (mode noob) : facile, on utilise un cube par pixel et on change sa couleur. Je vous laisse imaginer le nombre de prims... infaisable
Raisonnement n°2 (mode builder) : on peut diviser le nombre de prims par 5 en utilisant le fabuleux (si si !) prim "5 faces", qui permet d'afficher 5 faces carrées côte à côte avec un seul prim. Vous l'avez déjà tous vu avec les panneaux d'affichage de texte ou de score sur les jeux.
(Je vous ferai un post sur ce prim si vous voulez, pour ceux qui ne le connaitraient pas)

Raisonnement n°3 (mode scripteur) : C'est là ou j'en suis :
Avec le raisonnement n°2, on ne peut avoir que 5 pixels par prim, on doit pouvoir faire mieux...
C'est là qu'intervient la texture du concours. Cela ressemble un peu au principe du xxyztext, j'aurai très bien pu générer par exemple toutes les combinaisons de 6 pixels (ou plus, j'y reviendrai...), mais cela risquait de tenir en plusieurs texures, peut-être trop. Pour info le xxyztext utilise une bonne centaine de textures pour avoir toutes les combinaisons de 2 lettres...

Je voulais donc avoir toutes les combinaisons de 6 pixels possibles, sur une seule texture (petit défi perso et aussi pour moins de lag)

une tite image pour illustrer et expliquer le résultat (rigolez pas, c'est ma première utilisation de Gimp !) :
pixels_1.png

Pour info, j'avais à l'origine cherché à générer les combinaisons de 9pixels en carrés de 3x3, mais je n'ai pas réussi à trouver l'agencement des pixels, mon programme (pas optimal) de génération aurait mis plusieurs siècles pour explorer les combinaisons...

Une fois qu'on a compris le principe, ben il faut pouvoir en donner le contrôle à l'utilisateur.
Je fournis donc un mini langage d'instructions graphiques, que l'on peut soit écrire dans une notecard pour les non scripteurs, soit commander par script

Pour l'instant je fournis de quoi dessiner/afficher :
- des pixels isolés, des lignes, des rectangles, des cercles, du texte
- dessin interactif à la souris
- mémorisation d'une image complète pour pouvoir la redessiner d'un coup (après l'avoir dessinée par exemple)
- effets de fondu noir/blanc
+ d'autres un peu plus harcores pour optimiser
+ d'autres à venir...

Evidemment, avec les contrainte SL, faut pas s'attendre à du photoshop.
Je n'ai pas pu jouer avec l'alpha car le prim "5 faces" a des parties qui se superposent, du coup je reste en monochrome, on pourra néanmoins changer les couleurs des différentes faces (par bloc de 6 pixels du coup...)
Des contraintes mémoire (malgré beaucoup d'optim de ce côté là) limitent encore la résolution de l'image à 30x30 pixels, peut-être un peu plus. (La résolution peut être changée dynamiquement)

voici un petit exemple avec le script qui produit le résultat (les instructions dans le state_entry pourraient aussi être dans une notecard)

Demo1_001.png
(hého ce n'est qu'un exemple)
La résolution est de 30x30 pixels, il y a 30 prims utilisés pour l'affichage. Plus un prim root invisible qui pilote le tout (là ou il y a les scripts) + un prim pour faire la bordure tout autour.
J'ai utilisé une autre texture sur cet exemple qui laisse apparaître un bord noir autour des pixels, pour un effet différent.
Pour info le script se charge du build complet, j'expliquerai tout ça plus tard...

Je publierai les scripts (Il y en a 2, plus des scripts d'exemple d'utilisation, notamment un qui lit une notecard en boucle pour les non scripteurs ) dans très peu de temps, je suis en train de peaufiner quelques détails.
Je serai évidemment preneur de toute idée d'amélioration
Mince tu l'as vraiment fait la page blanche ou on peut écrire et dessiner . Je comprends toujours rien à ta texture malgré tes explications mais bravo pour ce script dont je trouve l'application "magique" et comme je l'avais dit c'est le seul truc qui me manquait sur SL .

Cela dit tu m'avais donné une idée et entretemps j'ai joué avec un script de particules qui me suit et me permet d'écrire ce que je veux en marchant simplement , juste un ptit truc à améliorer encore . Ce petit script tout bête au moins est à mon niveau . Le tien serait en chinois à mon avis je le comprendrai autant .

Bravo Redpurple pour avoir trouvé à quoi sert cette texture (qui m'a laissé perplexe depuis que je l'ai vu) .
Hé oui Smile

Je t'avais dit que tu frôlais la bonne réponse.
Tu as montré la lune en en parlant, mais en même temps tu ne regardais que ton doigt en disant que tu ne voyais pas de quoi il s'agissait !

Je prépare une petite doc pour voir si ça intéresse du monde et avoir quelques réactions...
j'aurai pas trouvé le mots pixel j'était proche pourtant avec le tableau alphabet
est ce que il y aura une démo sur sl?
bravo a redpurple
Citation :
Publié par milkcandy
j'aurai pas trouvé le mots pixel j'était proche pourtant avec le tableau alphabet
est ce que il y aura une démo sur sl?
bravo a redpurple
Oui, tu n'étais pas loin du tout. Mais s'agissant d'un concours, il fallait être assez précis

Je peux très bien faire une démo SL, mais pour l'instant c'est assez difficile pour moi, ayant déménagé RL, je dois me refaire une config PC assez puissante. Je suis pour l'instant avec un vieux portable pas performant du tout et qui chauffe grave (les captures viennent d'opensim en local, ca passe déjà mieux!)
Je peux me connecter mais à condition d'être à un endroit light : pas beaucoup de build et pas beaucoup d'avatar présent.

Sinon vous pourrez jouer avec dès que je publierai les scripts, avec indications pour le build (c'est pas compliqué du tout, juste des cubes à rezzer et lier)

Je t'envoie ton prix le temps de me connecter sans planter!
edit : voilà c'est fait. Manque plus que Redpurple
En guise d'apéritif, avant publication complète des scritps, voici une ébauche de doc résumant les commandes disponibles :

Code:
Conventions
  x, y , x1, y1 représentent des coordonnées d'affichage (abscisse, ordonnée). Entiers
  r représente un rayon. Nombre entier
  col représente une couleur : 0 pour noir, 1 pour blanc, -1 pour inverser
  fill représente un flag de remplissage : 0 = pas de remplissage, 1 = remplissage

CLS                      : Remplit l'écran en noir
FILL                     : Remplit l'écran en blanc
INVERT                   : Inverse l'image actuelle (négatif)
RAND                     : Remplit aléatoirement l'écran
PLOT x y col             : Dessine un pixel
LINE x1 y1 x2 y2 col     : Dessine une ligne
BOX x1 y1 x2 y2 col fill : Dessine un rectangle
CIRCLE x y r col fill    : Dessine un cercle
FADE type                : Fait un fondu progressif
  type = 0 : fondu vers le noir
  type = 1 : fondu vers le blanc
  (je bloque encore pour faire un fondu négatif, pas si simple...)
PAUSE duree              : effectue une pause
  duree en centièmes de secondes    
TEXT x y texte           : affiche un texte
  Attention, x multiple de 2 et y multiple de 3 (je n'ai pas géré les décalages binaires)
  pour l'instant les minuscules sont converties en majuscules
  caractères acceptés : 
  alphabet, chiffres et les caractères : !?+-()=/\/.,%$

IMAGE code : Restitue une image par son code
  le code est un texte qui représente l'image complete.
  Ce texte représente l'état binaire de toutes les faces du build, codé par un alphabet 
  de 64 caractères. C'est illisible mais les instructions CHAT ou MESSAGE permet 
  d'obtenir cette information pour pouvoir la copier ensuite.
  Par exemple :
  IMAGE aaaaaaaaaaaaaaaaa[W(Iaaar{W}aaa(%!%*Gaq-)!){aakAaqkkaffGaLfaaaaccqaaaacGcaaaaaaaaaaaaacaaaaaaaaqaaaaaaaaaaaaaaaaaaaakaaaaaaaa(Gaaaaaaaaaaampppoiaaaaaa
    
CHAT    : Envoie dans le chat public le codage de l'image. Utile pour utiliser ensuite 
  avec la fonction IMAGE
MESSAGE : Idem, mais l'information est envoyée au propriétaire seulement (par IM)

BUILD resolutionX largeur

  Première instruction à lancer. OBLIGATOIRE!
  Cela permet de builder toute la structure et d'initialiser beaucoup de paramètres 
  nécessaires au script.
  Les prims sont tous redimensionnés et positionnés comme il faut. 
  Ils sont également renommés.
  
  ResolutionX indique combien on veut de pixels en largeur. Nombre entier forcément 
  multiple de 10. (puisque chaque prim permet d'afficher 10 pixels en largeur)
  Il n'est pas utile de préciser la résolution en hauteur, celle ci sera déterminée en 
  fonction des prims faisant partie du build. Pour l'affichage des pixels vous devez 
  impérativement nommer les prims par un nom commençant par PIXEL, ce sont ceux qui 
  seront dimensionnés et positionnés automatiquement (ils seront également renommés pour
  connaitre leur position)
  Les scripts devront etre placé dans un autre prim qui devra etre root (évolution en 
  cours pour pouvoir avoir un autre root, afin de pouvoir lier à un autre build)
  
  Largeur représente la largeur du build en mètres. Nombre réel (par ex 8.5)
  Vous pouvez dépasser 10 mètres, faites néanmoins attention aux limites de distances 
  entre les prims d'un linkset. Voir également juste en dessous la remarque pour le cadre
  Vous devez également avoir un prim nommé CADRE, pour faire joli autour des pixels :)
  Il sera automatiquement dimensionné et positionné (mais pas texturé, vous le lookez 
  comme vous voulez).
  Si votre largeur dépasse 10m il ne pourra pas dépasser cette taille. Mais vous pouvez 
  utiliser un megaprim qui sera positionné sans être redimensionné (pas encore 
  d'instruction pour ça, il faut modifier un paramètre dans le script)
  
  Pour éviter un build "inutile" car ça peut être long, dans le cas d'une notecard lue en
  boucle par exemple, la commande build n'a d'effet que si on change un de ses paramètres.
  On peut ainsi s'amuser à changer la résolution et la taille dynamiquement, au milieu 
  d'une notecard par exemple.
  
INTERACT duree
  Permet de passer en mode interactif. c.a.d qu'on peut cliquer directement sur l'écran 
  pour allumer ou éteindre des pixels.
  Le paramètre duree permet de spécifier comment arreter le mode interactif :
  0 : on reste en mode interactif jusqu'à ce que l'utilisateur signale qu'il a terminé en 
      cliquant sur la bordure (évolution à venir : pouvoir cliquer sur un autre prim )
  >0 : nombre de secondes avant la fin du mode interactif. Le script reprend alors le 
       contrôle. J'ai mis ce paramètre dans l'idée d'une démo en boucle, afin de ne pas 
       stopper la démo si les utilisateurs ne cliquent pas sur la bordure.
  Une utilisation pratique de cette commande est de la faire suivre par une commande CHAT,
  afin d'obtenir le code de l'image dessinée pour l'utiliser avec la commande IMAGE.
  Il est possible (par script) d'obtenir le nom de l'avatar venant de terminer une image
  en mode interactif (sera expliqué dans une doc plus complète)
  
 
 Quelques commandes un peu plus hardcore, nécessitent la compréhension du binaire. Ces 
 commandes sont utilisées en interne par le script, mais peuvent être appelées de 
 l'extérieur si on veut optmiser certains tracés ou autre...
 
 SETALLBOX number
   number est un entier de 0 à 63 représentant un motif binaire pour les 6 pixels d'une 
   face. Toutes les faces de l'écran sont dessinées avec ce motif. 
   par exemple CLS équivaut à SETALLBOX 0, et FILL équivaut à SETALLBOX 63
   SETALLBOX 3 permet par exemple de remplir l'écran avec des lignes horizontales
   
 ANDALLBOXRND nbit
 ORALLBOXRND  nbit
 XORALLBOXRND nbit
   Ces commandes permettent de manipuler par opération binaire un certains nombre de bits
   de toutes les faces (blocs de 6 pixels) de l'écran. nbit indique combien de bits 
   (de 0 à 6) vont être modifiés. Ceux ci sont choisis de façon aléatoire. (commandes
   utilisées pour les fondus)
   On peut par exemple ajouter des parasites à une image avec ORALLBOXRND 1
   
 SETBLOCK x y number
   Dessine le motif binaire de 6 pixels correspondant à "number" sur la face contenant 
   le pixel x y
   
 SETMEGA x y n1 n2
   Permet de dessiner directement en binaire un bloc de 6x6 pixels.
   Ce qui correspond à 3 faces de 6 pixels en haut et 3 faces de 6 pixels en bas.
   n1 représente le codage binaire de la ligne du haut, sauf que maintenant on n'est plus
   sur 6 bits mais 18. n2 représente le codage binaire de la ligne du bas.
   Cette commande est utilisée pour l'affichage des lettres, par exemple pour afficher la
   lettre A en haut à gauche : SETMEGA 0 0 236776 40970
   TEXT 0 0 A est beaucoup plus simple :)  mais on peut utiliser SETMEGA pour d'autres 
   motifs que des lettres (je pense à un damier par exemple, un pixel sur deux d'allumé...)

   
 Quelques évolutions à venir (pas encore fait la spec n'est pas définitive)
  - PRIMSTOP nomduprim : pour choisir le prim a cliquer qui arrete l'interaction 
  - TEXTURE nomtexture : pour changer la texture utilisée, on pourra relooker les pixels
  - ALLCOL r v b : changer la couleur des pixels blancs (sur tout l'écran)
  - COL x y r g b : changer la couleur du bloc de 6 pixel contenant le pixel x y
  - possibilité de placer les script ailleurs que dans le root, pour pouvoir lier l'écran
    à un autre build
  - COPY/PASTE mémoriser et restituer une image plus tard
  - fonctions GET/SET pour lire/modifier certains paramètres
Félicitation, à Barbidule pour nous avoir tenus en halètements ...
et aux deux gagnantes pour leurs persévérances

Ca faisait longtemps que j'avais donné ma langue au chat !

Je ne suis pas sure d'avoir compris, cette image sert à extraire toutes les combinaisons possible de pixels d'un rectangle de 3 lignes 2 colonnes ...
N'étant pas scripteuse, je ne savais pas qu'il y avait des difficultés à "adresser" des pixels
Un concours pas pour moi, mais amusant au début
Bises.
Citation :
Publié par Kurieuse
Je ne suis pas sure d'avoir compris, cette image sert à extraire toutes les combinaisons possible de pixels d'un rectangle de 3 lignes 2 colonnes ...
Bises.
C'est exactement cela qu'a parfaitement résumé RedPurple.

La difficulté est à peu près la même que pour les afficheurs de texte qui permettent d'obtenir 2 lettres sur chacune des 5 faces du fameux prim "5faces"

Si c'est encore un peu mystérieux voici un gros plan d'un seul prim en mode édition :
pixels_2_001.png
On voit bien qu'on a 6 pixels sur chacune des 5 faces. On peut donc gérer 30 pixels par prim.

Pour ceux qui ne connaissent pas le prim "5 faces", regardez bien les paramètres géométriques dans la boite d'édition, recopiez les dans un cube (qui est en fait un prisme troué, tronqué), et aplatissez le ensuite selon l'axe des X. Pour certains build cela peut vous faire économiser pas mal de prims

edit: On voit bien sur les bords de la face du milieux qu'il y a un peu de superposition. C'est à cause de cela que je n'ai pas pu mettre de la transparence dans la texture, car ça laissait apparaitre des bouts de texture "parasites". C'est bien dommage, il y aurait certainement eut des améliorations possibles avec de la transparence...
@redpurple : j'attend toujours ton nom SL, car j'ai trouvé 2 redpurple et je suis pas sur du bon...

Sinon, publication pour demain soir ou après demain. Je dois encore tester quelques modifs, sous opensim. Puis tester dans la vraie grille pour voir s'il n'y a pas le retour du maudit "stack heap collision".

edit : tests ok sous opensim
+ quelques nouveautés :
- Possibilité d'avoir des nombre aléatoires dans les coordonnées
- Répétition n fois d'une commande (pratique pour les trucs aléatoires)

Reste à tester dans SL, (je laisse le pc refroidir un peu avant...)..
Bon, ça fonctionne dans SL
(Quelques bagarres avec la mémoire, mais c'est résolu)

Je vous balance donc tout ça :

Un petit résumé du mode opératoire :

Le build
Pour un écran de 30x30 pixels :
1) rezzez un cube, nommez le "pixel" (sans les guillemets)
2) dupliquez le jusqu'à en avoir 30 en tout
3) rezzez un cube, nommez le "cadre"
4) liez tout ca
5) rezze un cube, nommez le comme vous voulez, sauf un nom qui commence par pixel ou cadre, disons "ecran".
6) liez le cube "ecran" au reste, de façon à ce qu'il soit root (sélectionnez le en dernier avant de lier)
On doit avoir un build de 32 prims qui s’appelle "ecran"

Le contenu du build
Placez dans le build, c.a.d dans le prim root :
1) la texture du concours, en la nommant : 2x3p2_256_CarresFondNoirBordsNoirs
2) Les deux scripts "kernel0" et "kernel1" que voici :

kernel0 :

Code PHP:

integer gResoX 0;   // doit etre un multiple de 10
integer gResoY;        // sera calculé en fonction du nb de prims

integer gInteractLimit 0;
string gLastDrawer="";
float   gSizeLargeur 0.0// largeur totale en metres
// attention, la largeur du cadre est a retirer (cf gBorderSize)
// des 4 cotés, si on prend 10m en tout et 10cm de cadre, les pixels
// seront dimensionnés dans un espace de 9.8m en largeur
// la resolution en hauteur dependra du nombre de prims enfants dans le build

string gTextureName "2x3p2_256_CarresFondNoirBordsNoirs";
//string gTextureName = "2x3p2_256_CarresFondNoirGrille";
//string gTextureName = "2x3p2_256_CarresFondNoir";
vector gPixelColor = < 0.01.00.0>;

string gChildName "PIXEL"// debut du nom des prims enfants pris en compte
// (majuscules/minuscules indifferent)
// les prims utilisés doivent tous etres nommés PIXEL.
// ils seront renommés à l'initialisation du script en fonction de leur
// position, par exemple avec cette disposition pour une resoX de 30 pixels
// et 6 prims enfants nommés PIXEL avant init :
// PIXEL0_0  PIXEL1_0   qui donne 2 colonnes de 5 faces et 3 lignes de 1 face
// PIXEL0_1  PIXEL1_1   soit en largeur 2*5*2 = 20 pixels
// PIXEL0_2  PIXEL1_2   et en hauteur   3*1*3 = 9 pixels
integer gLenPrefix// sera la longueur de gChildName -1 (pour indexer)
float gChildEpaisseur 0.03// epaisseur des prims pixel
// (pas 0.01 car il y a des interferences de textures sur des faces se croisant)
integer gNbColPrims// nb de prims en largeur, sera calculé
integer gNbChildPrims=0// nb de prims pixel, sera calculé
integer gNbFaces=0// nb de face, = gNbChildPrims*5 sera calculé

// dans la foulee, on peut aussi avoir un cadre
string gBorderName "CADRE";
float gBorderSize 0.2// epaisseur du cadre autour des pixels, en metres.
float gEpaisseur 0.2;
float gDistanceCadre 0.01// distance des pixels au cadre
integer gIsMegaBorder 0// mettre à 1 pour ne pas resizer un megaprim
                          // Si vous utilisez un megaprim, sa taille doit
                         // etre ordonnée ainsi : <epaisseur, largeur, hauteur>
                        // c.a.d un pixel (x,y) (0,0 en haut à gauche)
                       // se place sur le cadre dans < 0.0, x, y > ( -y en fait)
// les prims enfants seront alignés et taillés pour rentrer dans "gResoX"
float gFactorSizeY 0.8615// taille réelle du 5faces qui est plus petit
                            // que son enveloppe. un 5faces d'1 metre mesure
                           // en fait 0.8615m
integer gLastRnd 0;

// constantes pour les numéro de faces des 5faces
integer FACE_1      3;
integer FACE_2      7;
integer FACE_3      4;     integer FACE_HAUT   0;
integer FACE_4      6;     integer FACE_BAS    5;
integer FACE_5      1;     integer FACE_DOS    2;

vector OffSetHautGauche(integer face)
{        if ( 
face == ) return <-0.1885,  0.3300.0>;
    else if ( 
face == ) return <-0.328 ,  0.3300.0>;
    else if ( 
face == ) return <-0.6495,  0.3300.0>;
    else if ( 
face == ) return <-0.328 ,  0.3300.0>;
    else                  return <-
0.464 ,  0.3300.0>;
}
vector OffSetBasDroite(integer face)
{        if ( 
face == ) return < 0.467, -0.326 0.0>;
    else if ( 
face == ) return < 0.329, -0.326 0.0>;
    else if ( 
face == ) return < 0.007, -0.32620.0>;
    else if ( 
face == ) return < 0.329, -0.326 0.0>;
    else                  return < 
0.192, -0.326 0.0>;
}
vector TexturesRepeat(integer face)
{        if ( 
face == ) return <  0.4650.275 0.0>;
    else if ( 
face == ) return <  0.1850.275 0.0>;
    else if ( 
face == ) return < -3.1100.275 0.0>;
    else if ( 
face == ) return <  0.1850.275 0.0>;
    else                  return <  
0.4440.275 0.0>;
}
 
vector ClickMin(integer face)
{        if ( 
face == ) return < 0.01.00.0>;
    else if ( 
face == ) return < 0.01.00.0>;
    else if ( 
face == ) return < 0.11.00.0>;
    else if ( 
face == ) return < 0.01.00.0>;
    else                  return < 
0.61.00.0>;
}
vector ClickMax(integer face)
{        if ( 
face == ) return < 0.40.00.0>;
    else if ( 
face == ) return < 1.00.00.0>;
    else if ( 
face == ) return < 0.0460.00.0>;
    else if ( 
face == ) return < 1.00.00.0>;
    else                  return < 
1.00.00.0>;
}

string gMatriceBin "32 00 16 36 08 20 40 04 56 48 52 57 50 53 58 33 62 44 29 46 28 45 14 24 31 43 23 59 39 27 51 54 07 26 37 30 41 22 60 61 49 38 25 55 42 21 63 47 12 09 06 13 10 05 15 11 03 02 01 19 34 17 35 18 ";
//a encoder?
//              0         1         2         3         4         5         6
//              0123456789012345678901234567890123456789012345678901234567890123
string gBase64="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()[]{}%$+-*!";

string gScreen// stockera les valeurs binaires de chaque face
             // dans l'ordre vers la droite puis le bas : c.a.d pour
            // des prims "pixelX_Y" avec X croissant puis Y croissant
string gSetScreen// globale pour dessiner une image en dur
                // because en parametre de SetImage -> stack heap error

vector gLastXYTouched = < -1.0, -1.00.0>;

string gPixelFaces ""
// contiendra la liste des faces des prims pixel
// sous la forme num_prim*5 + face-1, sur 3 carateres, sera mkangee

string TERM="end";
////////////////////////////////////////////////////////////////////////////////
integer Name2LinkNumber(string name)
{   
integer nbPrims llGetNumberOfPrims();
    
integer i;

    for (
i=0i<=nbPrims; ++i) if (llGetLinkName(i) == name) return i;

    return -
1;
}
// Name2LinkNumber 

Say(string msg){llOwnerSay(msg);}
// Say 

string Encode64(string Src)
{   
// Src = "xx xx xx ... xx " XX de 00 a 63
    
integer len llStringLength(Src);
    
integer i;
    
string result "";
    
integer num;

    for(
i=0i<leni+=3//attention +2 ou +3
    
{
        
num = (integer)llGetSubString(Srcii+1);
        
result += llGetSubString(gBase64numnum);
    }
// for
    
return result;
}
// Encode64 

vector Number2Offset(integer faceinteger number)
// retourne l'offset de texture correspondant au nombre binaire
    // pour la face "face"

    // recherche la position dans la matrice
    
string n3 llGetSubString("000" + (string)number, -2, -1);
    
integer pos llSubStringIndex(gMatriceBinn3);
    if (
pos == -1)
    {
        
Say("ERROR Number2Offset : " n3 " pas dans la matrice");
        return 
ZERO_VECTOR;
    }
    
pos pos/3;
    
integer col pos 8;
    
integer lig pos 8;

    
// calcul de l'offset
    
vector offset1 OffSetHautGauche(face);
    
vector offset2 OffSetBasDroite(face);

    
float dx = (offset2.offset1.x)/7.0;
    
float dy = (offset2.offset1.y)/7.0;

    return 
offset1 + < dx*coldy*lig0.0>;

}
// Number2Offset 

integer Face2Index(integer numPriminteger face)
{
    
// renvoie l'index dans gScreen correspondant à la face (1 a 5) du prim
    
string nom llGetLinkName(numPrim);
    
integer xinteger y;  // pour le prim nommé "pixelX_Y"
    
integer pos llSubStringIndex(nom"_");

    
// une ptite verif
    
if ( pos == -1) {   Say("ERROR Face2Index : pas d'underscore dans " nom);
                        return -
1// ===== EXIT =====
                    
}

    
= (integer)llGetSubString(nomgLenPrefix+1pos-1);
    
= (integer)llGetSubString(nompos+1, -1);

    
integer result y*5*gNbColPrims x*face-1;

    return 
result;

}
// Face2Index 

SetBlockNumber(integer xinteger yinteger n)
{
    
// recherche le nom du prim
    
integer xprim x/10;
    
integer yprim y/3;
    
string nom gChildName + (string)xprim "_" + (string)yprim;
    
integer nprim Name2LinkNumber(nom); 
    
    
SetNumberFace(nprim, (x/2)%1n);
}
// SetBlockNumber

SetMegaBlock(integer xinteger yinteger n1integer n2)
{
    
SetBlockNumber(x,yn1>>12);
    
SetBlockNumber(x+2,y, (n1>>6) & 63);
    
SetBlockNumber(x+4,yn1 63);
    
SetBlockNumber(x,y+3n2>>12);
    
SetBlockNumber(x+2,y+3, (n2>>6) & 63);
    
SetBlockNumber(x+4,y+3n2 63);
}
// SetMegaBlock

integer BuildFace2NumFace(integer face)
{        if (
face == FACE_1) return 1; else if (face == FACE_2) return 2;
    else if (
face == FACE_3) return 3; else if (face == FACE_4) return 4;
    else  return 
5;
}
// BuildFace2NumFace

integer NumFace2BuildFace(integer face)
{        if (
face == 1) return FACE_1; else if (face == 2) return FACE_2;
    else if (
face == 3) return FACE_3; else if (face == 4) return FACE_4;
    else return 
FACE_5;
}
// NumFace2BuildFace

SetNumberFace(integer numPriminteger faceinteger number)
{
    
integer vraieFace NumFace2BuildFace(face); // car face de 1 a 5
    
vector offset Number2Offset(facenumber);

    
llSetLinkPrimitiveParamsFastnumPrim
                                  
, [ PRIM_TEXTURE
                                    
vraieFace
                                    
gTextureName
                                    
TexturesRepeat(face)
                                    , 
offset
                                    
0.0
                                    
]);
    
// mise a jour de gScreen
    
integer index Face2Index(numPrimface);

    
string num3 llGetSubString("000" + (string)number, -2, -1) + " ";
    if (
index == 0)
        
gScreen num3 llGetSubString(gScreen3, -1);
    else if (
index == gNbChildPrims*5-1)
        
gScreen llGetSubString(gScreen0, -4) + num3;
    else 
gScreen llGetSubString(gScreen0index*3-1)
                 + 
num3
                 
llGetSubString(gScreenindex*3+3, -1);

}
// SetNumberFace

integer GetNumberFace(integer numPriminteger face)
{   
// renvoie le nombre binaire correspondant à la face du prim
    
integer i Face2Index(numPrimface);
    return (integer)
llGetSubString(gScreeni*3i*3+2);
}
// GetNumberFace

SetTouchXOR(integer numPriminteger numFacevector touchXY)
{
    
integer face BuildFace2NumFace(numFace);
    
integer num GetNumberFace(numPrimface);

    
// recupere le poids binaire cliqué, dépend de la face
    
vector clickMinvector clickMax// coordonnées du rectangle cliquable

    
clickMin ClickMin(face); 
    
clickMax ClickMax(face); 

    
vector xy touchXY clickMin;
    
vector dd clickMax clickMin;
    
integer lig = (integer)(3.0*xy.y/dd.y); // (integer)(3.0*[0.0, 1.0[) = 0,1,2
    
integer col = (integer)(2.0*xy.x/dd.x); // (integer)(2.0*[0.0, 1.0[) = 0,1

    
integer numBit lig*col;// car col va dans l'autre sens
    // (wé, j'aurai du faire mes n° de bit dans l'autre sens...)

    
integer newNum num ^ (1<<numBit);

    
SetNumberFace(numPrimfacenewNum);

}
// SetTouchXOR 

Plot(integer Xinteger Yinteger C)
{   
// affiche un pixel aux coordonnées X,Y
    // de couleur C : 0 noir, 1 allumé, -1 : inversion de couleur)

    
if ( (X<0) || (X>=gResoX) || (Y<0) || (Y>=gResoY) ) return;

    
// determination du prim a modifier
    
integer xPrim X/10;
    
integer face   = (10)/1// >>
    
integer yPrim Y/3;
    
string nom gChildName + (string)xPrim "_" + (string)yPrim;
    
integer numPrim Name2LinkNumber(nom);

    
// determination du binaire a changer
    
integer currentBin GetNumberFace(numPrimface);

    
// poids du bit correspondant au pixel
    
integer lig Y%3;
    
integer col X%2;

    
integer numBit lig*col// cf SetTouchXOR
    
integer poids 1<<numBit;

         if ( 
== SetNumberFace(numPrimfacecurrentBin & (63 poids));
    else if ( 
== SetNumberFace(numPrimfacecurrentBin poids);
    else if ( 
== -1SetNumberFace(numPrimfacecurrentBin poids);
}
// Plot 

Line(integer x1integer y1integer x2integer y2integer C
// algo bresenham trop lourdingue, je fais a ma sauce...
    
integer dx x2 x1float fdx llFabs((float)dx);
    
integer dy y2 y1float fdy llFabs((float)dy);
    
integer i;
    
float depart;float d;
    
integer delta 0;
    
    
Plot(x1y1C);
    if ( (
dx == 0) && (dy == 0) ) return;  // cas batard

    
if ( fdx fdy )
    {   
// boucle sur x
        
= (float)dy/fdx;
        
depart = (float)y1 d;
        if ( 
dx 0delta 1; else delta = -1;
        for(
i=x1i!=x2+= delta)
        {
            
Plot(i+delta, (integer)llRound(depart), C);
            
depart += d;
        }
    }
    else
    {   
// boucle sur y
        
= (float)dx/fdy;
        
depart = (float)x1 d;
        if ( 
dy 0delta 1; else delta = -1;
        for(
i=y1i!=y2+= delta)
        {
            
Plot((integer)llRound(depart), i+deltaC);
            
depart += d;
        }
    }
}
// Line 

Circle(integer x0integer y0integer rinteger Colinteger fill)
{
    
integer y ;
    
integer xmininteger lastxmin x0;
    
integer xmaxinteger lastxmax x0;
    
float dx;
    
integer i;

    for(
= -<= 0; ++y// on part du haut
    
{
        
dx = (float)(r) * llCos(llAsin( (float)y/(float)));
        
        
xmin x0 - (integer)dx 1;
        
xmax x0 + (integer)dx;

        if (
fill == 1
        {
            for(
i=xmini<=xmax;++i
            {
                
Plot(iy0 -1Col);
                
Plot(iy0 yCol);
            }
        }
        else
        {
            if (
xmin<lastxmin
            {
                for(
i=xmin;i<lastxmin;++i
                {
                    
Plot(iy0 -1Col);
                    
Plot(iy0 yCol);
                }
            }
            else
            {
                
Plot(xminy0 -1Col); 
                if (
y!=0
                
Plot(xminy0 yCol);
            }
            
            if ((
lastxmax<xmax) && (xmax>xmin) )
            {
                for(
i=lastxmax+1;i<=xmax;++i)
                {
                    
Plot(iy0 y-1Col);  
                    
Plot(iy0 yCol);
                }
            }
            else if (
xmax>xmin)
            {
                
Plot(xmaxy0 y-1Col); 
                if (
y!=0Plot(xmaxy0 yCol);
            }
            
lastxmin xmin;
            
lastxmax xmax;            
        }
// if fill
    
}// for y
    
}// Circle 

Box(integer x1integer y1integer x2integer y2integer Cinteger fill)
{
    
integer iinteger j;
    if (
x1>x2) { i=x1x1=x2x2=i;}
    if (
y1>y2) { i=y1y1=y2y2=i;}

    for(
i=x1;i<=x2;++iPlot(i,y1,C);//ligne du haut
    
for(j=y1+1;j<y2;++j// lignes au milieu
    
{
        
Plot(x1,j,C); //bord gauche
        
if (fill == 1) for(i=x1+1;i<x2;++iPlot(i,j,C); // pixels au milieu
        
if (x2>x1Plot(x2,j,C); // bord droite
    
}
    if (
y2>y1// ligne du bas
    
{
        for(
i=x1;i<x2;++iPlot(i,y2,C);
        if (
x2>x1Plot(x2,y2C);
    }
}
// Box 

string InitPrims()
{   
// intialise le build et quelques globales
    // renvoie "" si tout va bien, un message d'erreur sinon
    
integer i;              // variable de boucle
    
string nom;             // pour le nom d'un child prim
    
string prefix;         // debut du nom pour comparer au prefix
    
integer y 0integer x 0// pour ecrire x et y dans le nom
    
list listParams// utilise pour le llSetLinkPrimitivesParamFast

    
integer numberFill 0// motif binaire pour init de toutes les faces
                            // 0= vide, 63 = plein
    
string nFill3 "00 ";  // idem en chaine

    
integer nb llGetNumberOfPrims();
    
gChildName llToUpper(gChildName); // comme ca c'est fait...
    
gBorderName llToUpper(gBorderName); // pô de jaloux !
    
gLenPrefix llStringLength(gChildName) - 1;    // -1 pour index à 0

    
rotation localRot llEuler2Rot(DEG_TO_RAD * <0.00.090.0>);

    
// aplatissement du prim maitre pour ne pas gener les touch
    
vector size llGetScale();
    
llSetLinkPrimitiveParamsFastLINK_THIS, [ PRIM_SIZE, < size.x0.03size.z>,
                                               
PRIM_COLOR ALL_SIDES, <1.0,1.0,1.0>, 0.0
                                              
]);
    
// on va deja compter combien on a de prims PIXEL ---------------------
    
gNbChildPrims=0;
    for (
i=2i<=nb; ++i// le root_prim est le n°1, on le prend pas
    
{
        
nom llToUpper(llGetLinkName(i));
        
prefix llGetSubString(nom0gLenPrefix);
        if ( 
prefix == gChildName ) ++gNbChildPrims;
    }

    if (
gNbChildPrims == 0) return "ERROR INIT :aucun prim " gChildName " trouvé";
    
// -------------------------------------------------------// == EXIT ==
    
gNbFaces gNbChildPrims*5;
    
    
// on va deja calculer la taille de chaque prim enfant
    
gNbColPrims = (integer)(gResoX/10.0); // 10 pixels par prim en largeur

    
float largeurVisible = (gSizeLargeur gBorderSize*2.0)/(float)gNbColPrims;
    
float largeurReelle  largeurVisible/gFactorSizeY;
    
float hauteur 1.5*largeurVisible/5.0// ratio 3/2
    
size = < gChildEpaisseurlargeurReellehauteur >;

    
float hauteurTotale = (float)(gNbChildPrims) * hauteur / (float)gNbColPrims;
    
gScreen "";

    
// boucle sur tous les prims enfants ---------------------------------
    
for (i=2i<=nb; ++i// le root_prim est le n°1, on le prend pas
    
{
        
nom llToUpper(llGetLinkName(i));

        
// gestion du cadre -------------------------------
        
if ( nom == gBorderName )
        {
            if (
gIsMegaBorder == 0llSetLinkPrimitiveParamsFast(
                                        
, [ PRIM_SIZE
                                            
, < gEpaisseur
                                              
gSizeLargeur
                                              
hauteurTotale 2.0*gBorderSize
                                              
>
                                            , 
PRIM_ROT_LOCALlocalRot
                                            
PRIM_POSITIONZERO_VECTOR
                                            
]);
            else 
// on ne resize pas un megaprim
                                    
llSetLinkPrimitiveParamsFast(
                                        
, [ PRIM_ROT_LOCALlocalRot
                                            
PRIM_POSITIONZERO_VECTOR
                                            
]);
        }

        
// gestion des pixels ----------------------------
        
prefix llGetSubString(nom0gLenPrefix);
        if ( 
prefix == llToUpper(gChildName) )
        {
            
nom llToUpper(gChildName) + (string)"_" + (string)y;

            
//dimensionne, place et build les prims 5 faces
            
listParams = [ PRIM_TYPE
                         
PRIM_TYPE_PRISM
                            
PRIM_HOLE_SQUARE
                            
, < 0.199,0.8,0.0 >// cut = debut et fin de decoupe
                            
0.3              // hollow = creux / 100
                            
, < 0.0,0.0,0.0 >  // twist = debut et fin de vrille
                            
, < 1.0,1.0,0.0 >  // top_size = 1 - biseautage
                            
, < 0.0,0.0,0.0 >  // top_shear = inclinaison
                         
PRIM_SIZEsize
                         
PRIM_NAMEnom
                         
PRIM_POSITION // bon la j'avoue, j'en ai méga chié pour
                         // positionner les prims autour du root
                         
, < // -x*largeurVisible
                             // +((float)gNbColPrims * largeurVisible )/2.0
                             // - largeurVisible/2.0  allez une ptite facto :
                             
largeurVisible * ( (float)(gNbColPrims-1)/2.0 )
                           , 
gEpaisseur/2.0 gDistanceCadre
                           
, -y*hauteur + (hauteurTotale-hauteur)/2.0
                           
>
                         , 
PRIM_ROT_LOCALlocalRot
                         
PRIM_TEXTURE
                            
FACE_1gTextureNameTexturesRepeat(1)
                            , 
Number2Offset(1numberFill), 0.0
                         
PRIM_TEXTURE
                            
FACE_2gTextureNameTexturesRepeat(2)
                            , 
Number2Offset(2numberFill), 0.0
                         
PRIM_TEXTURE
                            
FACE_3gTextureNameTexturesRepeat(3)
                            , 
Number2Offset(3numberFill), 0.0
                         
PRIM_TEXTURE
                            
FACE_4gTextureNameTexturesRepeat(4)
                            , 
Number2Offset(4numberFill), 0.0
                         
PRIM_TEXTURE
                            
FACE_5gTextureNameTexturesRepeat(5)
                            , 
Number2Offset(5numberFill), 0.0
                         
PRIM_COLOR ALL_SIDESgPixelColor1.0
                         
PRIM_FULLBRIGHTALL_SIDESTRUE
                         
PRIM_COLORFACE_HAUTgPixelColor 0.0
                         
PRIM_COLORFACE_BAS gPixelColor 0.0
                         
PRIM_COLORFACE_DOS gPixelColor 0.0
                         
];

            
//if (gFlagBuild == 1) 
            
llSetLinkPrimitiveParamsFast(ilistParams);
            
            
gPixelFaces += llGetSubString("000" + (string)(i*0), -3, -1)
                         + 
llGetSubString("000" + (string)(i*1), -3, -1)
                         + 
llGetSubString("000" + (string)(i*2), -3, -1)
                         + 
llGetSubString("000" + (string)(i*3), -3, -1)
                         + 
llGetSubString("000" + (string)(i*4), -3, -1);

            
gScreen += nFill3 nFill3 nFill3 nFill3 nFill3;
            
gResoY y*3+3// pas apres la boucle car y peut etre incremente

            // pas optimal mais bon, c'est que l'init, ca perd pas grand chose
            
++x; if ( >= gNbColPrims ) { x=0; ++y; }

        }
// if ( prefix == llToUpper(gChildName) )
    
}// for (i=2; i<=nb; ++i)

    
MelangeFaces();

    return 
"";

// InitPrims 

MelangeFaces()
{
    
integer iinteger j;
    
string num3;
    
    for(
j=0j<gNbFaces; ++j)
    {
        
= (integer)llFrand((float)(gNbFaces-1))+1// sauf le 1er

        
num3 llGetSubString(gPixelFacesi*3i*3+2);
        if (
== gNbFaces-1)
            
gPixelFaces num3 llGetSubString(gPixelFaces0, -4);
        else 
gPixelFaces num3
                         
llGetSubString(gPixelFaces0i*3-1)
                         + 
llGetSubString(gPixelFacesi*3+3, -1);
    }
// for j
}// MelangeFaces 

        
////////////////////////
// quelques effets
////////////////////////
SetAllRandom()
{
    
integer i;
    
string numinteger priminteger face;

    
MelangeFaces();
    for (
i=0i<gNbFaces; ++i)
    {
        
num llGetSubString(gPixelFacesi*3i*3+2);
        
prim = ((integer)num)/5;
        
face = ((integer)num)%1;
        
SetNumberFaceprimface, (integer)llFrand(64.0));
    }
}
// SetAllRandom

integer RandomNumberBitCount(integer nBitSet)
{
    
integer numinteger n;

         if (
nBitSet == 0num 0;
    else if (
nBitSet == 6num 63;
    else if (
nBitSet == 1)
    {   
2*(integer)(llFrand(6.0));
        
num = (integer)llGetSubString("010204081632",nn+1);
    }
    else if (
nBitSet == 2)
    {   
2*(integer)(llFrand(15.0));
        
num = (integer)llGetSubString("030509173306101834122036241048",nn+1);
    }
    else if (
nBitSet == 3)
    {   
2*(integer)(llFrand(20.0));
        
num = (integer)llGetSubString("0711193513213725414914223826425028445256"
                                     
nn+1);
    }
    else if (
nBitSet == 4)
    {   
2*(integer)(llFrand(15.0));
        
num = (integer)llGetSubString("152339274351294553573046545860",nn+1);
    }
    else 
// forcement 5
    
{   2*(integer)(llFrand(6.0));
        
num = (integer)llGetSubString("626159554731",nn+1);
    }

    return 
num;
}
// RandomNumberBitCount

SetAllRandomBitCount(integer nBit)
{
    
integer i;
    
string numinteger priminteger face;

    
MelangeFaces();
    for (
i=0i<gNbFaces; ++i)
    {
        
num llGetSubString(gPixelFacesi*3i*3+2);
        
prim = ((integer)num)/5;
        
face = ((integer)num)%1;

        
SetNumberFaceprimfaceRandomNumberBitCount(nBit));
    }
}
// SetAllRandomBitCount

AndAllRandomBitCount(integer nBitfloat proba)
{
    
integer i;
    
string numinteger priminteger face;

    
MelangeFaces();
    for (
i=0i<gNbFaces; ++i)
    {
        
num llGetSubString(gPixelFacesi*3i*3+2);
        
prim = ((integer)num)/5;
        
face = ((integer)num)%1;

        if(
llFrand(1.0)<proba)
          
SetNumberFaceprimface
                       
GetNumberFace(prim,face) & RandomNumberBitCount(nBit));
    }
    
}
// SetAllRandomBitCount 

OrAllRandomBitCount(integer nBitfloat proba)
{
    
integer i;
    
string numinteger priminteger face;
    
    
MelangeFaces();
    for (
i=0i<gNbFaces; ++i)
    {
        
num llGetSubString(gPixelFacesi*3i*3+2);
        
prim = ((integer)num)/5;
        
face = ((integer)num)%1;

        if(
llFrand(1.0)<proba)
          
SetNumberFaceprimface
                       
GetNumberFace(prim,face) | RandomNumberBitCount(nBit));
    }
    
}
// OrAllRandomBitCount 

XOrAllRandomBitCount(integer nBitfloat proba)
{
    
integer i;
    
string numinteger priminteger face;

    
MelangeFaces();
    for (
i=0i<gNbFaces; ++i)
    {
        
num llGetSubString(gPixelFacesi*3i*3+2);
        
prim = ((integer)num)/5;
        
face = ((integer)num)%1;

        if(
llFrand(1.0)<proba)
          
SetNumberFaceprimface
                       
GetNumberFace(prim,face) ^ RandomNumberBitCount(nBit));
    }
    
}
// XOrAllRandomBitCount

SetAllNumber(integer n)
{
    
integer i;
    
string numinteger priminteger face;

    
MelangeFaces();
    for (
i=0i<gNbFaces; ++i)
    {
        
num llGetSubString(gPixelFacesi*3i*3+2);
        
prim = ((integer)num)/5;
        
face = ((integer)num)%1;
        
SetNumberFaceprimfacen);
    }
    
}
// SetAllNumber

SetImage64()
{
    
integer i;
    
string numinteger priminteger face;
    
integer idx;
    
integer n;
    
    
MelangeFaces();
    for (
i=0i<gNbFaces; ++i)
    {
        
num llGetSubString(gPixelFacesi*3i*3+2);
        
prim = ((integer)num)/5;
        
face = ((integer)num)%1;
        
idx Face2Index(prim,face);

        
llSubStringIndex(gBase64llGetSubString(gSetScreenidxidx));
        
SetNumberFace(primfacen);
    }
    
}
// SetImage64

Fondu(integer C)
{   
// C = couleur = 0 ou 1 ou -1 (inversion)

    
float p0 0.1float p1 0.1;
    
integer i;

    if ( 
== 0// fondu noir
    
{
        for(
i=0i<3; ++iAndAllRandomBitCount(3-i0.9);
        
SetAllNumber(0);
    }
    else if ( 
== // fondu blanc
    
{
        for(
i=0i<3; ++iOrAllRandomBitCount(3+i0.9);
        
SetAllNumber(63);
    }
}
// Fondu

integer Eval(string txt)
{
    
// nombre normal
    
if (llGetSubString(txt,0,0) != "R") return (integer) txt;
    
    if (
txt == "RLAST") return gLastRnd;
    
    
//cas nombre aleatoire, txt = Rn1-n2
    
integer n1integer n2integer pos;
    
pos llSubStringIndex(txt"-");
    
    if (
pos == -1)
    { 
        
Say("Error Eval : missing '-'");
        return 
0;
    }
    
n1 = (integer)llGetSubString(txt1pos-1);
    
n2 = (integer)llGetSubString(txtpos+1, -1);
    
    
gLastRnd = (integer)llFrand((float)(n2 n1 1)) + n1;
    
    return 
gLastRnd;
}
InfoScreen(string txt)
{
    
llSay(0" encoded image to copy: \nIMAGE " Encode64(txt) + "\n ");
}
Message(string txt)
{
    
llInstantMessage(llGetOwner(), gLastDrawer " sended : \nIMAGE " Encode64(txt) + "\n ");
}
////////////////////////////////////////////////////////////////////////////////
default
{
    
state_entry()
    {
    }
// state_entry ------------------------------------------------------------

    
link_message(integer sender_numinteger numstring strkey id)
    {
        if (
num != 42) return; // ==== EXIT ====

        
string msg str;
        
string cmd;
        
string p1string p2string p3string p4string p5string p6;

        
//str de la forme "command par1 par2 par3..."
        
str llToUpper(llStringTrim(strSTRING_TRIM));
        
        
// recherche des parametres ( oui y a mieux, mais stack-heap collision
        //                           -> listes bannies !!!)
        
integer pos llSubStringIndex(str" ");

        if ( 
pos == -// commandes sans parametres
        
{
            if      (
str=="CLS"    SetAllNumber(0);
            else if (
str=="FILL"   SetAllNumber(63);
            else if (
str=="RAND"   SetAllRandom();
            else if (
str=="INVERT" XOrAllRandomBitCount(61.0);
            else if (
str=="CHAT"   InfoScreen(gScreen);
            else if (
str=="MESSAGE"Message(gScreen);
            else 
Say("Commande inconnue 0: " msg);

            
jump fin_message//------------------------------------------------
        
}

        
cmd llGetSubString(str0pos-1);
        
str llStringTrim(llGetSubString(msgpos+1, -1), STRING_TRIM);
        
// msg pour l'image pas en majuscules
        
pos llSubStringIndex(str" ");

        if ( 
pos == -1// 1 parametre (dans str)
        
{
            if      (
cmd=="FADE" Fondu((integer)str);
            else if (
cmd=="IMAGE" ) { gSetScreen strSetImage64();}
            
// faire un IMAGE BEGIN/END pour avoir une image sur plusieurs lignes...
            
else if (cmd=="SETALLBOX" SetAllNumber((integer)str);
            
// faire des OR, AND, XOR avec une valeur fixe (non random)
            
else if (cmd=="ANDALLBOXRND" )
                
AndAllRandomBitCount((integer)str1.0);
            else if (
cmd=="ORALLBOXRND"  )
                
OrAllRandomBitCount((integer)str1.0);
            else if (
cmd=="XORALLBOXRND" )
                
XOrAllRandomBitCount((integer)str1.0);
            else if (
cmd=="INTERACT"
            {
                
gInteractLimit = (integer)str;
                
state Interact;
            }
            else 
Say("Commande inconnue 1: " msg);

            
jump fin_message//------------------------------------------------
        
}

        
p1 llGetSubString(str0pos-1);
        
str llStringTrim(llGetSubString(strpos+1, -1), STRING_TRIM);
        
pos llSubStringIndex(str" ");

        if ( 
pos == -1// 2 parametres ( p2 dans str)
        
{   
            if (
cmd=="BUILD"// build resoX taille
            
{
                
integer newgResoX = (integer)p1;
                
float newgSizeLargeur = (float)str;
                if ((
newgResoX != gResoX) || (newgSizeLargeur != gSizeLargeur))
                {
                    
gResoX newgResoX;
                    
gSizeLargeur newgSizeLargeur;
                    
string result InitPrims();
                    if (
result != ""Say(result "\n ERROR BUILD");
                }
            }
            else            
                
Say("Commande inconnue 2: " msg);
            
jump fin_message//------------------------------------------------
        
}

        
p2 llGetSubString(str0pos-1);
        
str llStringTrim(llGetSubString(strpos+1, -1), STRING_TRIM);
        
pos llSubStringIndex(str" ");

        if ( 
pos == -1// 3 parametres ( p3 dans str)
        
{
            if      (
cmd=="PLOT" )
                
Plot(Eval(p1), Eval(p2), (integer)str);
            else if (
cmd=="SETBLOCK")
                
SetBlockNumber(Eval(p1), Eval(p2), (integer)str);
            else
                
Say("Commande inconnue 3: " msg);
            
jump fin_message//------------------------------------------------
        
}

        
p3 llGetSubString(str0pos-1);
        
str llStringTrim(llGetSubString(strpos+1, -1), STRING_TRIM);
        
pos llSubStringIndex(str" ");

        if ( 
pos == -1// 4 parametres ( p4 dans str)
        
{
            if      (
cmd=="SETMEGA" )
                
SetMegaBlock( (integer)p1, (integer)p2
                            
, (integer)p3,(integer)str);
            else
            
Say("Commande inconnue 4: " msg);
            
jump fin_message//------------------------------------------------
        
}

        
p4 llGetSubString(str0pos-1);
        
str llStringTrim(llGetSubString(strpos+1, -1), STRING_TRIM);
        
pos llSubStringIndex(str" ");

        if ( 
pos == -1// 5 parametres ( p5 dans str)
        
{
            if      (
cmd=="CIRCLE" //Circle(x0, y0, r, Col, fill)
                
Circle( Eval(p1), Eval(p2), Eval(p3)
                      , (integer)
p4, (integer)str
                      
);
            else if (
cmd=="LINE" //Line(x1, y1, x2, y2, Col)
                
Line( Eval(p1), Eval(p2), Eval(p3), Eval(p4), (integer)str );
            else
                
Say("Commande inconnue 5: " msg);
            
jump fin_message//------------------------------------------------
        
}

        
p5 llGetSubString(str0pos-1);
        
str llStringTrim(llGetSubString(strpos+1, -1), STRING_TRIM);
        
pos llSubStringIndex(str" ");

        if ( 
pos == -1// 6 parametres ( p6 dans str)
        
{
            if      (
cmd=="BOX" //Box(x0, y0, x1, y1, Col, fill)
                
Box( Eval(p1), Eval(p2), Eval(p3), Eval(p4)
                   , (integer)
p5, (integer)str  );
            else

            
Say("Commande inconnue 6: " msg);
            
jump fin_message//------------------------------------------------
        
}
        
        @
fin_message;
        
llSetText(TERM, <1.00.00.0>, 0.0);

    }
// link_message -----------------------------------------------------------

}// default ====================================================================

state Interact
{
    
state_entry()
    {
        
//verouille la fin de commande
        
llSetText((string)gInteractLimit, <1.00.00.0>, 0.0);
        if (
gInteractLimit != 0llSetTimerEvent(1.0); 
    }
    
    
timer()
    {
        
gInteractLimit--;
        
llSetText((string)gInteractLimit, <1.00.00.0>, 0.0);
        if (
gInteractLimit == 0)
        {
            
llSetText(TERM, <1.00.00.0>, 0.0);
            
state default;
        }
    }
    
    
touch_start(integer num)
    {
        
vector touchST llDetectedTouchST(0);
        
integer nPrim llDetectedLinkNumber(0);
        
integer face llDetectedTouchFace(0); 
        
string name llToUpper(llGetLinkName(nPrim));
        
string prefix llGetSubString(name0gLenPrefix);
        
        if ( 
prefix == gChildName 
        {
            
SetTouchXOR(nPrimfacetouchST);
            
gLastDrawer llKey2Name(llDetectedKey(0));
        }
        else if ( 
name == gBorderName)
        {
            
llSetText(TERM " " gLastDrawer, <1.00.00.0>, 0.0);
            
state default;
        }
    }

kernel1:
Code PHP:

integer gTimeLimit 30;

string TERM0="end";
string TERM="ok";
string gRetour="";

//-----------------------------------------------------------------------------
Cmd(string str)
{
    
string txt="";  
    
string retour="";
    
integer time llGetUnixTime();
    
// temoin d'attente
    
llSetText("running", <1.00.00.0>, 0.0);
    
llMessageLinked(LINK_THIS42str"");
    
    
// attend la fin de la commande ou un timeout. 
    
integer len llStringLength(TERM0)-1;
    
    
// pas de timeout pour interact
    
integer flag_interact 0;
    if (
llGetSubString(str,0,7) == "INTERACT"flag_interact=1;
    
    while( ( 
txt != TERM0 ) && ( (llGetUnixTime() - time gTimeLimit)
                                || (
flag_interact == 1) )
         )
    {
        
txt llList2String(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]), 0);
        
retour llStringTrim(llGetSubString(txtlen+1, -1), STRING_TRIM);
        
txt llGetSubString(txt0len);
    }
    
    if ( 
txt != TERM0 
    {    
        
gRetour "TIMEOUT : " retour;
    }
    
}
// Cmd -----------------------------------------------------------------------
integer Name2LinkNumber(string name)
{   
integer nbPrims llGetNumberOfPrims();
    
integer i;

    for (
i=0i<=nbPrims; ++i) if (llGetLinkName(i) == name) return i;

    return -
1;
}
// Name2LinkNumber -----------------------------------------------------------

Say(string msg){llOwnerSay(msg);}
// Say ------------------------------------------------------------------------

Text(integer xinteger ystring text)
{
    
integer i;
    
integer n llStringLength(text);
    
string car;
    
string com;

    for(
i=0i<n; ++i)
    {
        
car llToUpper(llGetSubString(textii));
        
com "setmega " + (string)" " + (string)" ";
        
        if      (
car == " "Cmd(com "0 0");
        else if (
car == "A"Cmd(com "236776 40970");
        else if (
car == "B"Cmd(com "244936 58114");
        else if (
car == "C"Cmd(com "168130 25352");
        else if (
car == "D"Cmd(com "94440 54018");
        else if (
car == "E"Cmd(com "244930 58120");
        else if (
car == "F"Cmd(com "244930 40960");
        else if (
car == "G"Cmd(com "169186 25354");
        else if (
car == "H"Cmd(com "240682 40970");
        else if (
car == "I"Cmd(com "15042 50056");
        else if (
car == "J"Cmd(com "15042 49792");
        else if (
car == "K"Cmd(com "239874 41032");
        else if (
car == "L"Cmd(com "172032 58120");
        else if (
car == "M"Cmd(com "190762 40970");
        else if (
car == "N"Cmd(com "190506 41034");
        else if (
car == "N"Cmd(com "190506 41034");
        else if (
car == "O"Cmd(com "168168 25346");
        else if (
car == "P"Cmd(com "244970 40960");
        else if (
car == "Q"Cmd(com "170216 25418");
        else if (
car == "R"Cmd(com "244970 41032");
        else if (
car == "S"Cmd(com "244962 49930");
        else if (
car == "T"Cmd(com "15042 640");
        else if (
car == "U"Cmd(com "172074 25346");
        else if (
car == "V"Cmd(com "172074 4672");
        else if (
car == "W"Cmd(com "174122 24962");
        else if (
car == "X"Cmd(com "26882 36936");
        else if (
car == "Y"Cmd(com "26882 640");
        else if (
car == "Z"Cmd(com "14786 54024");
        else if (
car == "1"Cmd(com "39552 50056");
        else if (
car == "2"Cmd(com "81098 58120");
        else if (
car == "3"Cmd(com "81130 49930");
        else if (
car == "4"Cmd(com "216544 840");
        else if (
car == "5"Cmd(com "244930 49930");
        else if (
car == "6"Cmd(com "236738 25354");
        else if (
car == "7"Cmd(com "13514 640");
        else if (
car == "8"Cmd(com "105672 25346");
        else if (
car == "9"Cmd(com "105704 17154");
        else if (
car == "0"Cmd(com "170216 25346");
        else if (
car == "!"Cmd(com "2688 512");
        else if (
car == "?"Cmd(com "40136 512");
        else if (
car == "+"Cmd(com "200352 640");
        else if (
car == "-"Cmd(com "199712 0");
        else if (
car == "("Cmd(com "2624 384");
        else if (
car == ")"Cmd(com "1408 576");
        else if (
car == "="Cmd(com "17160 4290");
        else if (
car == "/"Cmd(com "2306 36864");
        else if (
car == "\\"Cmd(com "26624 72");
        else if (
car == ":"Cmd(com "512 128");
        else if (
car == "."Cmd(com "0 512");
        else if (
car == ","Cmd(com "0 2304");
        else if (
car == "%"Cmd(com "10498 36872");
        else if (
car == "$"Cmd(com "106178 50050");

        
x+=6;
    }
// for
    
    
gRetour ""// penible à gerer ici...
    
}// Text ----------------------------------------------------------------------
        
default ///////////////////////////////////////////////////////////////////////
{   
    
state_entry()
    {
        
    }
// state_entry -----------------------------------------------------------
    
    
link_message(integer sender_numinteger numstring strkey id)
    {   
        
integer iinteger nb// pour la boucle du repeat
        
        
if (num != 0) return; // ==== EXIT ====
        
        
string linestring msgstring p1string p2string p3
        
string cmd;integer pos;
        
        
line llStringTrim(strSTRING_TRIM);
        
msg line;
        
pos llSubStringIndex(line" ");
        
cmd llStringTrim(llGetSubString(line0pos), STRING_TRIM);
        
cmd llToUpper(cmd);
            
        if ( 
pos == -// commandes sans parametres
        
{
            
Cmd(msg);
            
jump fin_message//-------------------------------------------
        
}
            
        
// au moins 1 param
        
line llStringTrim(llGetSubString(linepos+1, -1), STRING_TRIM);
        
pos llSubStringIndex(line" "); if (pos==-1pos=0;
        
p1 llStringTrim(llGetSubString(line0pos-1), STRING_TRIM);
        
        if (
pos == 0// 1 param
        
{
            if (
cmd=="PAUSE" 
            {
                
llSleep(((float)p1)/100.0);
            }
            else 
Cmd(msg);
            
jump fin_message//-------------------------------------------
        
}
            
        
// au moins 2 param
        
line llStringTrim(llGetSubString(linepos+1, -1), STRING_TRIM);
        
pos llSubStringIndex(line" "); if (pos==-1pos=0;
        
p2 llStringTrim(llGetSubString(line0pos-1), STRING_TRIM);
        
        
//cas particulier du REPEAT n cmd
        
if (cmd=="REPEAT")
        {
            
nb = (integer)p1;
            
cmd llStringTrim(lineSTRING_TRIM);
            for(
i=1i<=nb;i++) Cmd(cmd);
            
jump fin_message;
        }
        
        if (
pos == 0// 2 param
        
{
            
Cmd(msg);
            
jump fin_message//-------------------------------------------
        
}
            
        
// au moins 3 param
        
line llStringTrim(llGetSubString(linepos+1, -1), STRING_TRIM);
        
pos llSubStringIndex(line" "); if (pos==-1pos=0;
        
p3 llStringTrim(llGetSubString(line0pos-1), STRING_TRIM);
          
        if (
pos == 0// 3 param
        
{
            if (
cmd=="TEXT")
                
Text((integer)p1, (integer)p2p3);
            else
                
Cmd(msg);
            
jump fin_message//-------------------------------------------
        
}
            
        
Cmd(msg);
            
        @
fin_message;
        
llSetText(TERM " " gRetour, <1.0,0.0,0.0>, 0.0);
    }
// link_message

}// state default -------------------------------------------------------- 
Il ne se passe rien? c'est normal !
Vous avez là, la machinerie du truc. Ca ne fait qu'obéir aux instructions qu'on lui donne et on lui a encore rien donné...
(suite au prochain post because la taille)
La suite :

Pour donner des instructions de dessins, vous avez deux possibilités :
- soit piloter par script
- soit par une notecard

On va commencer par la méthode notecard:

Ajouter dans le build la notecard suivante, nommée DEMO1 :
Code:
BUILD 30 10.0
CLS
CIRCLE 15 19 8 1 0
PLOT 12 15 1
PLOT 17 15 1
LINE  10 20 12 22 1
LINE 12 22 17 22 1
LINE 17 22 19 20 1
LINE 0 6 4 6 1
LINE 4 6 8 10 1
LINE 8 10 8 6 1
LINE 8 6 29 6 1
TEXT 0 0 HELLO
PAUSE 300
FADE 1
BOX 2 2 27 27 0 0
BOX 4 4 25 25 0 0
BOX 0 0 7 7 -1 1
BOX 22 0 29 7 -1 1
CIRCLE 0 29 16 -1 1
CIRCLE 29 29 16 -1 1
PAUSE 200
INVERT
PAUSE 100
TEXT 12 6 5
PAUSE 100
TEXT 12 6 4
PAUSE 100
TEXT 12 6 3
PAUSE 100
TEXT 12 6 2
PAUSE 100
TEXT 12 6 1
PAUSE 100
TEXT 12 6 0
REPEAT 5 RAND
IMAGE aaaaaaaaaaaaaaaaa[W(Iaaar{W}aaa(%!%*Gaq-)!){aakAaqkkaffGaLfaaaaccqaaaacGcaaaaaaaaaaaaacaaaaaaaaqaaaaaaaaaaaaaaaaaaaakaaaaaaaa(Gaaaaaaaaaaampppoiaaaaaa
PAUSE 300
FADE 0
// attention, on joue en binaire maintenant!
SETALLBOX 1
PAUSE 50
SETALLBOX 3
PAUSE 50
SETALLBOX 11
PAUSE 50
SETALLBOX  43 
PAUSE 300
// encore plus hardcore !!
//damier de pixels en bas
SETMEGA 0 24 158118 104025
SETMEGA 6 24 158118 104025
SETMEGA 12 24 158118 104025
SETMEGA 18 24 158118 104025
SETMEGA 24 24 158118 104025
// quelques rectangles
SETMEGA 0 0 176343 240693
SETMEGA 6 6 176343 240693
SETMEGA 12 12 176343 240693
SETMEGA 16 6 176343 240693
SETMEGA 24 0 176343 240693
PAUSE 400
CLS
// quelques pixels aleatoires a droite
REPEAT 50 PLOT R17-29 R0-29 1
// des lignes verticales aleatoires (utilisation RLAST)
REPEAT 20 LINE R0-14 0 RLAST 29 -1
// the end
BOX 4 16 24 24 1 0
BOX 5 17 23 23 0 1
TEXT 6 18 END
PAUSE 200
PAUSE 300
Il ne se passe toujours rien, c'est encore normal!
Il manque un script pour lire la notecard et faire exécuter ses instructions :

script demo_notecard :
Code PHP:

// Exemple de script pour executer les commandes contenues dans une notecard
// pilotant les scripts 2x3p2_kernel0 et 2x3p2_kernel1

// nom de la notecard principale contenant les commandes
// "principale" car une évolution va etre de pouvoir utiliser plusieurs notecards
string  gNotecard "DEMO1";

// variables pour la lecture de la notecard
integer gNbLines 0;
integer gCurrentLine 0;
list    
gCommandes = [];
key     gRequest NULL_KEY;


//-----------------------------------------------------------------------------
Cmd(string str)
{   
// execute la commande passée en paramètre. C'est LA procédure à utiliser
    // dans vos scripts.
    
    
string txt=""
    
string retour=""
    
    
llSetText("running", <1.00.00.0>, 0.0);
    
// temoin d'attente, astuce "simple" pour oliger le script à attendre la
    // fin de la commande, sinon les llMessageLinked s'empileraient..
    // quand la commande est terminée, le hovertext est mis à "ok"
    // (plus d'autres informations fournies par certaines commandes)
    
    
llMessageLinked(LINK_THIS0str""); 
    
// attention, forcément 0 pour le nombre. 
    // comme les deux scripts "kernel" écoutent les messages linkés, il fallait éviter
    // des interférences. Le kernel1 réceptionne seulement les message ayant 0 comme
    // nombre passé en paramètre, qui éventuellement communique avec le kernel 0
    // qui n'écoute que le paramètre 42.
    
    // attend la fin de la commande. 
    // Malgrés les apparences ce n'est pas une boucle infinie, il y a un paramètre
    // qui garantit la fin de la commande au bout d'un certain temps, de façon à 
    // ce que le script principal (celui là, que vous lisez présentement) puisse
    // reprendre la main en cas de problèmes (lag...etc).
    // nb : pas de timeout si on utilise la commande INTERACT
    
while( retour != "ok" )
    {
        
txt llList2String(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]), 0);
        
retour llGetSubString(txt01);
        
txt llStringTrim(llGetSubString(txt2, -1), STRING_TRIM);
        
        
// retour ne contient que les 2 premiers caractères. car certaines commandes
        // envoient des informations complémentaires derrière le hovertext
        // on peut récupérer ici ces informations, dans la variable txt.
        
        // par exemple, la commande INTERACT permet d'avoir le nombre de secondes
        // restantes si on utilise ce paramètre. Quand l'utilisateur a fini de dessiner
        // on recupere son nom.
    
}
    
}
// Cmd -----------------------------------------------------------------------

Say(string msg){llOwnerSay(msg);} // pour centraliser le chat de debug
// Say ------------------------------------------------------------------------

// code "classique" de lecture de notecard .
// l'etat default ne sert qu'à lancer l'état read_notecard.
// l'etat read_notecard lit la notecard et stocke les lignes lues dans
// la liste gCommandes. Quand c'est fini, on passe à l'etat run_notecard
// qui execute les commandes une par une en boucle.

default ///////////////////////////////////////////////////////////////////////
{   
    
state_entry()
    {
        
state read_notecard;
    }
// state_entry -----------------------------------------------------------
    
    
on_rez(integer start_param) { llResetScript();} // utile? merite reflexion...
    
// default ------------------------------------------------------------------

state read_notecard ///////////////////////////////////////////////////////////
{   
    
state_entry()
    {
        
Say("lecture notecard " gNotecard " ...");
        
gRequest llGetNumberOfNotecardLines(gNotecard); 
        
llSetTimerEvent(5.0); // si jamais la carte est vide ou inexistante,
        // on n'aura pas l'evenement dataserver. on declenchera alors un 
        // message d'erreur au bout de 5 secondes d'attente.
        
    
}// state_entry -----------------------------------------------------------
    
    
timer() 
    {
        
llSetTimerEvent(0.0);
        
Say("Erreur : Notecard " gNotecard " vide ou inexistante.");
    }
// timer -----------------------------------------------------------------
    
    
dataserver(key query_idstring data)
    {
        if (
query_id == gRequest
        {
            
llSetTimerEvent(0.0); // c'est ok, on neutralise le message d'erreur
            
if (data == EOF
            {
                
state run_notecard;
            }
            else if (
gNbLines == 0// première requête du nombre de lignes
            
{
                
gNbLines = (integer)data;
                
gRequest llGetNotecardLine(gNotecardgCurrentLine); 
            }
            else 
// lecture d'une ligne
            
{
                
// on ne stocke pas les commentaires, ni les lignes vides
                
if (   llStringTrim(dataSTRING_TRIM) != "" 
                    
&& llGetSubString(data01) != "//"
                {
                    
gCommandes += [data]; //Say("data:" + data); 
                
}
                ++
gCurrentLine;
                
gRequest llGetNotecardLine(gNotecardgCurrentLine); 
            }
        }
// if (query_id == gRequest) 

    
}// dataserver ------------------------------------------------------------
    
// state read_notecard ------------------------------------------------------

state run_notecard ////////////////////////////////////////////////////////////
{
    
state_entry()
    {
        
Say("notecard " gNotecard " lue. Execution des commandes...");
        
string line
        
        
gNbLines llGetListLength(gCommandes);
        
        while(
TRUE)
        {
            for(
gCurrentLine=0gCurrentLine gNbLines; ++gCurrentLine)
            {
                
line llList2String(gCommandesgCurrentLine);
                
line llStringTrim(lineSTRING_TRIM);
           
                
Cmd(line);
            
            }
// for

        
}// while
        
    
}// state_entry -----------------------------------------------------------
    
    
changed(integer change)
    {
        
//reset automatique si on modifie la notecard
        
if (change CHANGED_INVENTORYllResetScript();
        
// ne fonctionne pas quand on execute les commandes car on est dans une
        // boucle infinie dans le state_entry, les événements ne peuvent pas se 
        // déclencher tant qu'on en est pas sorti...
        
    
}// changed ---------------------------------------------------------------

}// state run_notecard -------------------------------------------------------- 
La il devrait se passer des choses

Si vous voulez dessiner à la souris, remplacez le contenu de la notecard par :
Code:
BUILD 30 10.0
CLS
INTERACT 0
CHAT
Resetter le script demo_notecard
Quand le dessin est fini, vous pouvez cliquer sur le cadre pour avoir dans le chat le codage de l'image (pour utiliser avec la commande IMAGE)


2eme possibilité : si vous scriptez, vous n'aurez pas forcement envie d'une notecard, vous préférerez sans doute générer les commandes dynamiquement

Il vous faut alors écrire un script qui contient la procédure "Cmd", et puis c'est tout ! :

demo_run:
Code PHP:

// Exemple de script pour piloter les scripts 2x3p2_kernel0 et 2x3p2_kernel1
// Demo1 : dessinne une image rudimentaire avec quelques commandes simples.

//-----------------------------------------------------------------------------
Cmd(string str)
{   
// execute la commande passée en paramètre. C'est LA procédure à utiliser
    // dans vos scripts.
    
    
string txt=""
    
string retour=""
    
    
llSetText("running", <1.00.00.0>, 0.0);
    
// temoin d'attente, astuce "simple" pour oliger le script à attendre la
    // fin de la commande, sinon les llMessageLinked s'empileraient..
    // quand la commande est terminée, le hovertext est mis à "ok"
    // (plus d'autres informations fournies par certaines commandes)
    
    
llMessageLinked(LINK_THIS0str""); 
    
// attention, forcément 0 pour le nombre. 
    // comme les deux scripts "kernel" écoutent les messages linkés, il fallait éviter
    // des interférences. Le kernel1 réceptionne seulement les message ayant 0 comme
    // nombre passé en paramètre, qui éventuellement communique avec le kernel 0
    // qui n'écoute que le paramètre 42.
    
    // attend la fin de la commande. 
    // Malgrés les apparences ce n'est pas une boucle infinie, il y a un paramètre
    // qui garantit la fin de la commande au bout d'un certain temps, de façon à 
    // ce que le script principal (celui là, que vous lisez présentement) puisse
    // reprendre la main en cas de problèmes (lag...etc).
    // nb : pas de timeout si on utilise la commande INTERACT
    
while( retour != "ok" )
    {
        
txt llList2String(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]), 0);
        
retour llGetSubString(txt01);
        
txt llStringTrim(llGetSubString(txt2, -1), STRING_TRIM);
        
        
// retour ne contient que les 2 premiers caractères. car certaines commandes
        // envoient des informations complémentaires derrière le hovertext
        // on peut récupérer ici ces informations, dans la variable txt.
        
        // par exemple, la commande INTERACT permet d'avoir le nombre de secondes
        // restantes si on utilise ce paramètre. Quand l'utilisateur a fini de dessiner
        // on recupere son nom.
    
}
    
}
// Cmd -----------------------------------------------------------------------

default
{
    
state_entry()
    {
        
Cmd("BUILD 30 10.0");
        
Cmd("CLS");
        
Cmd("CIRCLE 15 15 13 1 0");
        
Cmd("CIRCLE 10 9 2 -1 1");
        
Cmd("CIRCLE 20 9 2 -1 1");
        
Cmd("LINE 7 17 22 23 1");
        
Cmd("LINE 7 23 22 17 1");
        
Cmd("BOX 0 14 29 29 -1 1");
    }

Les scripts demo_notecard et demo_run sont relativement "clean" (j'espère!), je les ai bien commenté je crois.
Beaucoup vont hurler en voyant les kernel0 et kernel1!!! Il y a du pas propre du tout dedans et beaucoup de code non conventionnel.
L'analyse de syntaxe des commandes est horrible, mais je devais me passer des listes au maximum pour des raisons d'occupation mémoire, et différencier les commandes par leur nombre d'argument faisait un code moins long. Mais ca reste horrible à lire...
Pour le reste, j'ai du supprimer beaucoup de commentaire et de mise en forme, toujours pour des raisons d'occupation mémoire ("stack heap collision"). De même que les listes sont remplacées par des chaines, et certaines sont compactées... Ca ne simplifie pas la lecture du code, qui est en plus déjà complexe...

Si vous avez un problème, genre ça se bloque ou autre, je vous conseille la manip suivante :
1) stopper votre script principal (demo_notecard ou demo_run)
2) réinitialiser kernel1, puis kernel0
2) réinitialiser votre script principal et le relancer.

Dés évolutions sont encore à venir (j'ai une grosse idée pour la mémoire, mais ca casse presque tout le code...).
C'est pour l'instant une version qui tourne assez correctement, que je qualifierai donc de beta 1.0

Toute remarque, suggestion sont bienvenues
Pas de retours... sniff, ça doit être les vacances...

En attendant le projet prend de l'envergure

- optimisations mémoire pour augmenter la résolution (je n'ai pas testé jusqu'où on pouvait aller, mais l'optim est grosse...)

- stabilisation des scripts pour une réinitialisation automatique "propre", plus la peine de se demander dans quel ordre il faut réinitialiser quoi.

- diverses commandes supplémentaires (gestion de couleurs, d'hovertext, d'alpha...)

- possibilité d'avoir un autre prim root pour lier à un autre build, et surtout possibilité de lier plusieurs écrans entre eux, vivant leur vie indépendamment les uns des autres ou bien pilotés par une notecard (ou un script) centrale. Permet d'avoir des affichages multi écrans, mais aussi de tricher pour augmenter la résolution (on est alors limité par la le nombre de prims d'un linkset)

C'est encore en test (la partie multi-écran est écrite mais pas testée encore), je ne publierai pas les scripts ici car c'est assez long, néanmoins je fournirai un lien avec une doc complète (en cours d'écriture) et les scripts.
Citation :
Publié par bestmomo
Joli boulot le bidule ...
Merci à toi momo++

Dommage que tu ais du préférer les cocotiers, le sable fin et les vahinés plutôt que de participer (je vois pas pourquoi )... Tu aurais pu faire concurrence à Redpurple (qui d'ailleurs s'obstine à ne pas me dire son nom pour recevoir son prix )
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés