|
Comme suite à la demande de anpton j'ai fait une nouvelle version du pack "articulation". Cette fois pour un axe et de multiples primitives. C'est le cas pour les volets. Le principe reste pratiquement le même avec une axe et ce script :
//////////////////////////////////////////////////////////////////////////////////////////////// // // // Articulation Multi Axe V 1.00 // // // //////////////////////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2012 by Bestmomo Lagan // //////////////////////////////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // (at your option) any later version. // // // // Articulations is distributed WITHOUT ANY WARRANTY; // // See the GNU General Public License for more details. // // // // To get a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>. // ////////////////////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------- // Paramètres // -----------------------------------------------
integer CANAL_SETUP = -2253610;
// ----------------------------------------------- // Etat par défaut // ----------------------------------------------- default { state_entry() { // Ecoute setup llListen(CANAL_SETUP + 1, "", NULL_KEY, ""); }
listen(integer channel, string name, key id, string message) { if(message == "DIE") llDie(); else // Réponse à demande de position et rotation llSay(CANAL_SETUP, "SET@" + (string)llGetPos() + "@" + (string)llGetRot()); } }
Un setup :
//////////////////////////////////////////////////////////////////////////////////////////////// // // // Articulation Multi Setup V 1.00 // // // //////////////////////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2012 by Bestmomo Lagan // //////////////////////////////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // (at your option) any later version. // // // // Articulations is distributed WITHOUT ANY WARRANTY; // // See the GNU General Public License for more details. // // // // To get a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>. // ////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////// // Parameters that you can change // ////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////// // Dont change code below unless you know what you do // ////////////////////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------- // Variables de travail // ----------------------------------------------- integer i_canal_menu; float f_angle;
// Axe vector v_axe;
// ----------------------------------------------- // Variables de paramétrage // ----------------------------------------------- // Numéro de liaison de la prim list l_link;
// Position de l'axe vector v_centre_axe;
// Rotation des prims pour les deux états list l_r_rot_state_1; list l_r_rot_state_2;
// Position des prims pour les deux états list l_v_pos_state_1; list l_v_pos_state_2;
// Rotation des vecteurs tournants rotation r_vec_rot;
// ----------------------------------------------- // Paramètres à ne pas toucher // ----------------------------------------------- integer CANAL_SETUP = -2253610;
// ----------------------------------------------- // Canal aléatoire // ----------------------------------------------- integer genCanal() { return ~(integer)llFrand((float)DEBUG_CHANNEL); } // ----------------------------------------------- // Gestion des menus // ----------------------------------------------- // Envoi du menu à l'owner set_menu(string texte, list menu) { llDialog(llGetOwner(), texte, menu, i_canal_menu); } // Menu de sélection des primtives menu_prims() { list l = ["End"]; set_menu("Click all primitives to be moved and \"End\" when it's done", l); } // Menu de réglage rotation menu_setup() { set_menu("\nAdjust prims and click \"End\" if it's adjusted" , ["-1","End","+1","-5","< >","+5","-20","< >","+20","-90","< >","+90"]); }
// ----------------------------------------------- // Passage de position globale <-> locale // ----------------------------------------------- vector global_to_local(vector position) { return (position - llGetRootPosition()) / llGetRootRotation(); }
// ----------------------------------------------- // Passage de rotation globale <-> locale // ----------------------------------------------- rotation rot_to_local(rotation rot) { return rot / llGetRootRotation(); }
// ----------------------------------------------- // Paramètres primitive // ----------------------------------------------- set_texte(integer id, vector col) { llSetLinkPrimitiveParamsFast(id, [PRIM_TEXT, "Selected", <1,1,1>, 1]); } unset_texte(integer id) { llSetLinkPrimitiveParamsFast(id, [PRIM_TEXT, "", <0,0,0>, 0]); } vector get_pos(integer id) { return llList2Vector(llGetLinkPrimitiveParams(id, [PRIM_POS_LOCAL]), 0); } rotation get_rot(integer id) { return llList2Rot(llGetLinkPrimitiveParams(id, [PRIM_ROT_LOCAL]), 0); }
// ----------------------------------------------- // Sauvegardes informations // ----------------------------------------------- save_infos() { string s = "Copy all informations between lines into a notecard called \"articulation\"\n" + "---------------------------------------------------------------------------------------------------------\n" + (string) v_centre_axe + "@" + (string)r_vec_rot; integer n = llGetListLength(l_link); while(n--) { s += "\n" + (string)llList2Integer(l_link, n) + "@" + (string)llList2Vector(l_v_pos_state_1, n) + "@" + (string)llList2Vector(l_v_pos_state_2, n) + "@" + (string)llList2Rot(l_r_rot_state_1, n) + "@" + (string)llList2Rot(l_r_rot_state_2, n); } s += "\n---------------------------------------------------------------------------------------------------------\n"; llOwnerSay(s); }
// ----------------------------------------------- // Récupération des infos de l'axe // ----------------------------------------------- default { state_entry() { llOwnerSay(llGetScriptName() + " ready."); llSetText("Setup in progess...", <1,1,1>, 1); // Ecoute pour l'axe llListen(CANAL_SETUP, "", NULL_KEY, ""); // Message à l'axe llSay(CANAL_SETUP + 1, "ASK"); llSetTimerEvent(3.0); }
listen(integer channel, string name, key id, string message) { // Réception messages de l'axe list l = llParseString2List(message, ["@"], []); // Récupération des données de l'axe if(llList2String(l, 0) == "SET") { vector v_centre_global = (vector)llList2String(l, 1); rotation r_global = (rotation)llList2String(l, 2); v_centre_axe = global_to_local(v_centre_global); rotation r_local = rot_to_local(r_global); v_axe = llVecNorm(v_centre_axe + <.0,.0,1.0> * r_local - v_centre_axe); state prims; } }
timer() { llSetTimerEvent(3.0); llOwnerSay("No axis !"); // Message à l'axe llSay(CANAL_SETUP + 1, "ASK"); }
state_exit() { llSetTimerEvent(.0); } }
// ----------------------------------------------- // Définition des prims // ----------------------------------------------- state prims { state_entry() { // Canal pour le menu i_canal_menu = genCanal(); // Ecoute pour le menu llListen(i_canal_menu, "", llGetOwner(), ""); // Menu menu_prims(); }
listen(integer channel, string name, key id, string message) { if(message == "End") { if(llGetListLength(l_link)) state etats; else { llOwnerSay("You must select at least one prim !"); menu_prims(); } } }
touch_start(integer total_number) { integer id = llDetectedLinkNumber(0); // On ne doit pas prendre le root ni deux fois la même primitive ! if(id != 1 && llListFindList(l_link, [id]) == -1) { set_texte(id, <1,1,1>); // Mémorisation des informations l_link += id; l_v_pos_state_1 += get_pos(id); l_r_rot_state_1 += get_rot(id); } } }
// ----------------------------------------------- // Réglage du deuxième état // ----------------------------------------------- state etats { state_entry() { // Canal pour le menu i_canal_menu = genCanal(); // Ecoute pour le menu llListen(i_canal_menu, "", llGetOwner(), ""); // Menu menu_setup(); }
listen(integer channel, string name, key id, string message) { // Réception messages des menus if(channel == i_canal_menu) { // Touche neutre if(message == "< >" || message == " ") menu_setup(); // Fin du réglage else if(message == "End") { // Mémorisation état 2 integer i; integer n = llGetListLength(l_link); for(; i < n; ++i) { integer id_link = llList2Integer(l_link, i); l_v_pos_state_2 += get_pos(id_link); l_r_rot_state_2 += get_rot(id_link); } // Effacement des textes flottants unset_texte(1); while(n--) unset_texte(llList2Integer(l_link, n)); // Destruction de l'axe llSay(CANAL_SETUP + 1, "DIE"); // Enregistrement des informations save_infos(); // Fin llOwnerSay("Drop \"Articulation action\" script in object inventory"); llRemoveInventory(llGetScriptName()); } // Réglage en cours else { float f_valeur = (float)message; f_angle += f_valeur; r_vec_rot = llAxisAngle2Rot(v_axe, f_angle * DEG_TO_RAD); integer n = llGetListLength(l_link); // Mise en mouvement global while(n--) { integer id_link = llList2Integer(l_link, n); vector v_tournant = llList2Vector(l_v_pos_state_1, n) - v_centre_axe; llSetLinkPrimitiveParamsFast(id_link, [ PRIM_POSITION, v_centre_axe + v_tournant * r_vec_rot, PRIM_ROT_LOCAL, llList2Rot(l_r_rot_state_1, n) * r_vec_rot]); } menu_setup(); } } } }
Il suffit de positionner l'axe, de mettre le setup dans le root. Un menu apparaît et vous devez cliquer sur toutes les primitives concernées par le mouvement. Quand c'est fait vous cliquez sur le bouton "End", apparaît alors le menu pour le réglage. Quand c'est fini on demande de créer une notecard "articulation" avec les paramètres générés. Un truc comme ça :
<-0.75537, 0.00738, 0.13965>@<-0.00000, -0.17365, -0.00000, 0.98481>
2@<0.00000, 0.00000, 0.13057>@<-0.04245, 0.00000, 0.38947>@<0.00000, 0.00000, 0.00000, 1.00000>@<0.00000, -0.17365, 0.00000, 0.98481>
3@<0.00000, 0.75510, 0.14360>@<-0.04691, 0.75510, 0.40171>@<0.00000, 0.00000, 0.00000, 1.00000>@<0.00000, -0.17365, 0.00000, 0.98481>
4@<0.00000, 0.25510, 0.14360>@<-0.04691, 0.25510, 0.40171>@<0.00000, 0.00000, 0.00000, 1.00000>@<0.00000, -0.17365, 0.00000, 0.98481>
5@<0.00000, -0.24400, 0.14360>@<-0.04691, -0.24400, 0.40171>@<0.00000, 0.00000, 0.00000, 1.00000>@<0.00000, -0.17365, 0.00000, 0.98481>
6@<0.00000, -0.74400, 0.14360>@<-0.04691, -0.74400, 0.40171>@<0.00000, 0.00000, 0.00000, 1.00000>@<0.00000, -0.17365, 0.00000, 0.98481>
Il faut mettre la note dans le root accompagnée de ce script :
//////////////////////////////////////////////////////////////////////////////////////////////// // // // Articulation Multi Action V 1.01 // // // //////////////////////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2012 by Bestmomo Lagan // //////////////////////////////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // (at your option) any later version. // // // // Articulations is distributed WITHOUT ANY WARRANTY; // // See the GNU General Public License for more details. // // // // To get a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>. // ////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////// // Parameters that you can change // ////////////////////////////////////////////////////////////////////////////////////////////////
// Time float TIME = 2; // Transition time in seconds integer AUTO = FALSE; // TRUE for loop mode float RETURNTIME = 0; // Time for auto return to first position (0 for no auto-return) integer API = FALSE; // True for only API
// Access string ACCESS = "All"; // Access must be "All", "Group", "Owner" or "List" list ACCESSLIST = []; // Access names list if ACCESS is on "List"
// Sounds string SECONDSOUND = "none"; // Sound for second position ("none" if none) string FIRSTSOUND = "none"; // Sound for first position ("none" if none)
// Sensor float SENSOR_RANGE = 0; // Sensor range (0 for none), no touch action if sensor float SENSOR_DELAY = 4; // Sensor delay (no matter if no sensor)
// Messages string ACCESSMESSAGE = "Sorry but your are not allowed to command this object"; string CLICKMESSAGE = "Come closer to command this object";
// API integer API_CLICK = 211; // Like a "click" integer API_AUTO_START = 212; // Start in "auto" mode integer API_AUTO_STOP = 213; // Stop in "auto" mode integer API_GO_POS_1 = 214; // Go to first position integer API_GO_POS_2 = 215; // Go to second position integer API_GET_POS = 216; // To get position integer API_POS_ANSWER = 217; // POsition answer
//////////////////////////////////////////////////////////////////////////////////////////////// // Dont change code below unless you know what you do // ////////////////////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------- // Variables de paramétrage // ----------------------------------------------- // Numéro de liaison de la prim list l_link;
// Position de l'axe vector v_centre_axe;
// Rotation des prims pour les deux états list l_r_rot_state_1; list l_r_rot_state_2;
// Position des prims pour les deux états list l_v_pos_state_1; list l_v_pos_state_2;
// Rotation des vecteurs tournants rotation r_vec_rot;
// ----------------------------------------------- // Paramètres à ne pas toucher // ----------------------------------------------- float TEMPS_BASE = .04; string NOTECONFIG = "articulation";
// ----------------------------------------------- // Paramètres primitive // ----------------------------------------------- vector get_pos(integer id) { return llList2Vector(llGetLinkPrimitiveParams(id, [PRIM_POS_LOCAL]), 0); }
// ----------------------------------------------- // Variables de travail // ----------------------------------------------- integer i_auto;
// Pour lecture note integer iStep; key kQuery; integer iNotecardLine;
// ----------------------------------------------- // Fonctions pour lecture de la note // -----------------------------------------------
// Fonction qui lance la lecture de la note de configuration si présente read_config() { if(llGetInventoryType(NOTECONFIG) == INVENTORY_NOTECARD) { kQuery = llGetNotecardLine(NOTECONFIG, iNotecardLine++); llWhisper(0, "Reading notecard \"" + NOTECONFIG + "\"..."); } }
// Traitement de la note integer traite_note(string data) { if (data != EOF) { if(llGetSubString(data, 0, 1) != "//" && data != "" && data != " ") { list l = llParseString2List(data, ["@"], []); if(iStep++) { l_link += (integer)llList2String(l, 0); l_v_pos_state_1 += (vector)llList2String(l, 1); l_v_pos_state_2 += (vector)llList2String(l, 2); l_r_rot_state_1 += (rotation)llList2String(l, 3); l_r_rot_state_2 += (rotation)llList2String(l, 4); } else { v_centre_axe = (vector)llList2String(l, 0); r_vec_rot = (rotation)llList2String(l, 1); } } kQuery = llGetNotecardLine(NOTECONFIG, iNotecardLine++); return FALSE; } else return TRUE; }
// ----------------------------------------------- // Test d'accès // ----------------------------------------------- integer test_access(key id) { if(ACCESS == "List" && ~llListFindList(ACCESSLIST, [llKey2Name(id)])) return TRUE; else if(ACCESS == "Owner" && llGetOwner() == id) return TRUE; else if(ACCESS == "Group" && llSameGroup(id)) return TRUE; else if(ACCESS == "All") return TRUE; else return FALSE; }
// ----------------------------------------------- // Interpolation // ----------------------------------------------- rotation r_cos(rotation r0, rotation r1, float t){ float f = (1 - llCos(t * PI)) / 2; float f_ang = llAngleBetween(r0, r1); if(f_ang > PI) f_ang -= TWO_PI; return r0 * llAxisAngle2Rot(llRot2Axis(r1 / r0) * r0, f_ang * f); }
// ----------------------------------------------- // Transition // ----------------------------------------------- transition(integer i_back) { float f_step = 1.0 / (TIME / TEMPS_BASE); float step; while((step += f_step) <= 1.0) { integer n = llGetListLength(l_link); integer i; rotation r; list l_params; for(; i < n; ++i) { if(i_back) r = r_cos(r_vec_rot, ZERO_ROTATION, step); else r = r_cos(ZERO_ROTATION, r_vec_rot, step); vector v_tournant = llList2Vector(l_v_pos_state_1, i) - v_centre_axe; vector pos = v_centre_axe + v_tournant * r; if(i) l_params += [PRIM_LINK_TARGET, llList2Integer(l_link, i)]; l_params += [PRIM_POSITION, pos, PRIM_ROT_LOCAL, llList2Rot(l_r_rot_state_1, i) * r]; } llSetLinkPrimitiveParamsFast(llList2Integer(l_link, 0), l_params); llSleep(TEMPS_BASE); } }
// ----------------------------------------------- // Manoeuvre de l'objet // ----------------------------------------------- // Test de première position integer test_first() { return get_pos(llList2Integer(l_link, 0)) == llList2Vector(l_v_pos_state_1, 0); }
// Test de seconde position integer test_second() { return get_pos(llList2Integer(l_link, 0)) == llList2Vector(l_v_pos_state_2, 0); }
// Manoeuvre sur clic action_click() { // Vers second if(test_first()) { go_second(); } // vers premier else if(test_second()) { if(RETURNTIME == .0) go_first(); } // Cas où il y a eu une modification de build else { llSetText("", ZERO_VECTOR, 0); llResetScript(); } }
// Passage en seconde position go_second() { transition(FALSE); // Fixation de l'état integer n = llGetListLength(l_link); while(n--) { llSetLinkPrimitiveParamsFast(llList2Integer(l_link, n), [ PRIM_POSITION, llList2Vector(l_v_pos_state_2, n), PRIM_ROT_LOCAL, llList2Rot(l_r_rot_state_2, n)]); } if(SECONDSOUND != "none") llTriggerSound(SECONDSOUND, 1.0); else if(RETURNTIME != .0 && SENSOR_RANGE == .0 && !AUTO) llSetTimerEvent(RETURNTIME); }
// Passage en première position go_first() { transition(TRUE); // Fixation de l'état integer n = llGetListLength(l_link); while(n--) { llSetLinkPrimitiveParamsFast(llList2Integer(l_link, n), [ PRIM_POSITION, llList2Vector(l_v_pos_state_1, n), PRIM_ROT_LOCAL, llList2Rot(l_r_rot_state_1, n)]); } if(FIRSTSOUND != "none") llTriggerSound(FIRSTSOUND, 1.0); }
// ----------------------------------------------- // Etat d'initialisation // ----------------------------------------------- default { state_entry() { llWhisper(0, "Looking for notecard \"" + NOTECONFIG + "\"..."); read_config(); }
dataserver(key id, string data) { if(kQuery == id) { if(traite_note(data)) state marche; } }
changed(integer change) { if(change & CHANGED_INVENTORY) read_config(); } } // ----------------------------------------------- // Etat de fonctionnement // ----------------------------------------------- state marche { state_entry() { llWhisper(0, "Notecard \"" + NOTECONFIG + "\" read. All is OK."); // Retour en première position integer n = llGetListLength(l_link); while(n--) { llSetLinkPrimitiveParamsFast(llList2Integer(l_link, n), [ PRIM_POSITION, llList2Vector(l_v_pos_state_1, n), PRIM_ROT_LOCAL, llList2Rot(l_r_rot_state_1, n)]); } // Sensor éventuel if(SENSOR_RANGE != .0 && !API) llSensorRepeat("", NULL_KEY, AGENT, SENSOR_RANGE, PI, SENSOR_DELAY); // Marche automatique if(AUTO) { i_auto = TRUE; llSetTimerEvent(.01); } }
touch_start(integer total_number) { // On vérifie que le clic se fait sur une prim qui doit bouger if(~llListFindList(l_link, [llDetectedLinkNumber(0)]) && !API) { key k = llDetectedKey(0); if(test_access(k)) { if(SENSOR_RANGE == .0) action_click(); else if(test_first()) llInstantMessage(k, CLICKMESSAGE); } else llInstantMessage(k, ACCESSMESSAGE); } }
sensor(integer total_number) { // Gestion si objet en première position if(test_first()) { // Test de personnes autorisées while(total_number--) if(test_access(llDetectedKey(total_number))) { go_second(); return; } // Si personne autorisée on met en seconde si première else if(test_second()) go_first(); } }
no_sensor() { // Si personne on met en première if(test_second()) go_first(); }
link_message(integer sender_number, integer number, string message, key id) { if(number == API_CLICK && SENSOR_RANGE == .0) action_click(); else if(number == API_GO_POS_1) go_first(); else if(number == API_GO_POS_2) go_second(); else if(number == API_GET_POS) { llMessageLinked(LINK_THIS, API_POS_ANSWER, (string)test_second(), NULL_KEY); } else if(AUTO) { if(number == API_AUTO_START) { i_auto = TRUE; llSetTimerEvent(.01); } else if(number == API_AUTO_STOP) i_auto = FALSE; } }
timer() { llSetTimerEvent(.0); if(AUTO) { if(i_auto) { if(test_first()) go_second(); else go_first(); llSetTimerEvent(.01); } } else go_first(); } }
Et ça fonctionne comme pour les versions précédentes avec les mêmes paramètres.
Maintenant pour faire fonctionner les volets il faut évidemment faire tous les setups en commençant par celui-ci (parce qu'il manipule les textes flottants et du coup on perdrait les autres setup). Et après il faut utiliser les API. J'ai d'ailleurs mis à jour le script "action" (V 1.03) de l'autre version de "articulations" pour enrichir l'API. Mais j'expliquerai ça dans un prochain post .
Dernière modification par bestmomo ; 28/10/2012 à 16h50.
Motif: Changement du script d'action V 1.01
|