1. Bitte schaltet eure Ad Blocker aus. SLinfo kann nur betrieben werden, wenn es durch Werbung Einnahmen erzielt. Vielen Dank!!
    Information ausblenden
  2. Wir freuen uns, wenn du dich in unserem Forum anmeldest. Bitte beachte, dass die Freigabe per Hand durchgeführt wird (Schutz vor Spammer). Damit kann die Freigabe bis zu 24 Stunden dauern.
    Information ausblenden
  3. Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und die Zugriffe auf unsere Website zu analysieren. Sie geben Einwilligung zu unseren Cookies, wenn Sie unsere Webseite weiterhin nutzen.
    Information ausblenden

Skript erkennt, dass Textur auf Objekt gezogen wird.

Dieses Thema im Forum "Fragen zu Scripting" wurde erstellt von Kelith Resident, 14. Februar 2014.

  1. Kelith Resident

    Kelith Resident Aktiver Nutzer

    Beiträge:
    318
    Zustimmungen:
    2
    Punkte für Erfolge:
    0
    Hallo zusammen,
    ich suche eine Möglichkeit zu erkennen, ob eine Textur aus dem Inventar auf ein Objekt gezogen und losgelassen wurde. Das Skript soll dann eine bestimmte Fläche mit der Textur belegen. Ziel ist, das Objekt soll not modify sein und per Skript gewährleisten, dass immer nur die eine Fläche die Textur abbekommt, egal wo man die Textur auf dem Objekt tatsächlich hinzieht.
    Mit einem Touch Event geht das nicht, oder? Ich hatte mal was gefunden um eine Textur UUID per drag and drop in ein HUD zu bekommen, kann das aber leider nicht mehr finden. Mit einem gerezzten Objekt wie im aktuellen Fall müsste das doch dann auch gehen?
     
  2. MartinRJ Fayray

    MartinRJ Fayray Freund/in des Forums

    Beiträge:
    796
    Zustimmungen:
    2
    Punkte für Erfolge:
    18
    Hier sind Beispiele dazu:
    http://wiki.secondlife.com/wiki/Llallowinventorydrop

    Das würde dann z.B. so aussehen in deinem speziellen Fall:

    Code:
    integer iTextureFace = 1; //Seite des Prims, auf die die Textur gegeben werden soll.
    default
    {
      state_entry()
      {
       llAllowInventoryDrop(TRUE); //Das Ablegen von Inventar erlauben.
      }
      changed(integer change)
      {
        integer iNumberTextures = llGetInventoryNumber(INVENTORY_TEXTURE);
        key kTexture;
        if (change & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY))
        { //Der Owner (oder jemand mit Mod-Rechten: CHANGED_INVENTORY) oder jemand ohne Modify-Rechte (CHANGED_ALLOWED_DROP) hat das Inventar verändert.
          if (llGetInventoryNumber(INVENTORY_TEXTURE) > iNumberTextures)
          { //Es gibt eine neue Textur.
            kTexture = llGetInventoryKey(INVENTORY_TEXTURE, llGetInventoryNumber(INVENTORY_TEXTURE)-1); //Den Key der zuletzt eingefügten Textur auslesen.
            llSetTexture(kTexture, iTextureFace); //Die 'neue' Textur verwenden (falls jemand mit Modify-Permissions das Inventar verändert hat, wird die zuletzt eingefügte Textur verwendet).
          } //else: nichts tun.
        }
      }
    }
     
    Zuletzt bearbeitet: 14. Februar 2014
  3. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.993
    Zustimmungen:
    66
    Punkte für Erfolge:
    64
    Hallo Kellith

    Wenn die Textur auf ds Objekt gezogen wird, wird immer der changed() Ereignis ausgelöst.

    Wenn die Textur im Inventar des Objekt erscheint, dann wird CHANGED_INVENTORY aktiv sein, falls Du das Objekt bearbeiten kannst und die Textur ins Baufenster wirfst. Wenn die Textur bei der gedruckten STRG Taste geworfen wird (Objekt rot umrandet) dann CHANGED_ALLOWED_DROP. Und wenn die Textur direkt auf eine Fläche geworfen wurde und diese texturiert hat, ohne im Objektinventar zu erscheinen, dann CHANGED_TEXTURE. Im letzten Fall kannst du die Textur verwerfen und neu texturieren.

    Damit CHANGED_ALLOWED_DROP ausgelöst werden kann, must Du das via llAllowInventoryDrop() erlauben, auf die Weise können ADBoards die Bilder, Karten und andere Sachen aufnehmen.

    LG
     
  4. Dianna Loxely

    Dianna Loxely Superstar

    Beiträge:
    1.621
    Zustimmungen:
    4
    Punkte für Erfolge:
    0
    hmmm, mal resümieren:

    Objekt = nomod -> textur per maus auf die gewünschte fläche ziehen nicht möglich
    was möglich ist mit allowdrop, ist die textur ins inventar des nomod objektes zu schieben
    das muss ein skript im inneren dem face die neue textur zuweisen (inventory-changed -> settexture)
    dazu muss die textur fullperm sein, damit man die uuid der fremdtextur auslesen kann
     
  5. Kelith Resident

    Kelith Resident Aktiver Nutzer

    Beiträge:
    318
    Zustimmungen:
    2
    Punkte für Erfolge:
    0
    Hallo, vielen Dank für die Antworten so schnell :)

    @MartinRJ Fayray: Da ist ein Syntax error in Deinem Skript,
    Code:
    [COLOR=#494949]kTexture = llGetInventoryKey(INVENTORY_TEXTURE, llGetInventoryNumber(INVENTORY_TEXTURE)-1);[/COLOR]
    Das llGetInventoryKey erlaubt nur einen Parameter, es sollte wohl so ähnlich lauten?
    Code:
    [COLOR=#494949]kTexture = llGetInventoryKey(llGetInventoryNumber(INVENTORY_NAME));[/COLOR]


    Trotzdem war Dein Skript und die Anmerkung der anderen sehr hilfreich.
    Ich habe das hier gebastelt, so als erste Variante, die aber schon das tut, was sie soll. Eine erste Textur liegt bereits im Auslieferungszustand im Objekt. Deren Name wird gespeichert. Wenn eine zweite Textur hinzukommt (STRG-drag-drop), wird die erste gelöscht und die neue Textur gesetzt.

    Code:
    string  name;default
    {
     state_entry()
        {
             llAllowInventoryDrop(TRUE);                        // Das Ablegen von Inventar erlauben.
             name =  llGetInventoryName(INVENTORY_TEXTURE, 0);  // as default there is already one texture
    }
        changed(integer change)
        {
            if (change & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY))    // if there has been a change to the prim's contents ...
            {
                if (llGetInventoryNumber(INVENTORY_TEXTURE) > 1)        // if there is another texture
                {   
                    llRemoveInventory(name);                            // remove last known texture
                    if (name = llGetInventoryName(INVENTORY_TEXTURE, 0))  llSetTexture(name,1);  // if a texture exists set it
                }
            }
        }
    }
     
    Zuletzt bearbeitet: 14. Februar 2014
  6. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.993
    Zustimmungen:
    66
    Punkte für Erfolge:
    64
    llGetInventoryKey benötigt den Namen der Datei im Objektinventar um den Key dafür zu ermitteln. So müsste der Befehl funktionieren:

    Code:
    llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, 0));
    Ich würde im Skript die Textur übernehnem und danach wieder löschen, damit wenn jemand eine neue rein tut, sie oben erscheint. Evtl macht es sinn, alle Texturen zu löschen, falls einer einen Haufen reingelegt hat. Dann könnte es passieren, dass die vorhandene Texturen immer noch vorne sind und das Auslesen der Neuen blokieren. Dann legt man eine Textur und der Skript bringt eine andere auf die Vorderseite bis die von vor einer Stunde dran ist und man vielleicht einen Batzen von Texturkopien im Objekt liegen hat. So in etwa:

    Code:
    string name;
    
    default
    {
        state_entry()
        {
            llAllowInventoryDrop(TRUE); // Das Ablegen von Inventar erlauben.
    
            name =  llGetInventoryName(INVENTORY_TEXTURE, 0);
            while (name != "")
            {
                llSetTexture(name, 1);
                llRemoveInventory(name);
                name =  llGetInventoryName(INVENTORY_TEXTURE, 0);
            }
        }
    
        changed(integer change)
        {
            if (change & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY))    // if there has been a change to the prim's contents ...
            {
                name =  llGetInventoryName(INVENTORY_TEXTURE, 0);
                while (name != "")
                {
                    llSetTexture(name, 1);
                    llRemoveInventory(name);
                    name =  llGetInventoryName(INVENTORY_TEXTURE, 0);
                }
            }
        }
    }
    
    Kleines Manko, wenn man hier im Seltenen Fall 20 Texturen rein tut, wernden alle 20 nacheinander im Diashow abgespielt und die letzte bleibt angezeigt. Wäre sinnvoll evtl nur die letzte anzuzeigen. Das macht aber den Skript komplizierter.

    Wenn man aber fordert, dass da nur fullperm Texturen für den Tafelbesitzer in die Tafel landen, dann könnte man statt Namen den Key abfragen und den letzten Key dann nach der Löschschleife zuweisen.
     
    Zuletzt bearbeitet: 14. Februar 2014
  7. MartinRJ Fayray

    MartinRJ Fayray Freund/in des Forums

    Beiträge:
    796
    Zustimmungen:
    2
    Punkte für Erfolge:
    18

    Hopple, das sollte heißen:
    kTexture = llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, llGetInventoryNumber(INVENTORY_TEXTURE)-1)); // (die zuletzt ins Inventar eingefügte Textur)

    Das gesamte Skript sieht dann so aus (ich habe es nicht getestet):

    Code:
    integer iTextureFace = 1; //Seite des Prims, auf die die Textur gegeben werden soll.
    default
    {
      state_entry()
      {
       llAllowInventoryDrop(TRUE); //Das Ablegen von Inventar erlauben.
      }
      changed(integer change)
      {
        integer iNumberTextures = llGetInventoryNumber(INVENTORY_TEXTURE);
        key kTexture;
        if (change & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY))
        { //Der Owner (oder jemand mit Mod-Rechten: CHANGED_INVENTORY) oder jemand ohne Modify-Rechte (CHANGED_ALLOWED_DROP) hat das Inventar verändert.
          if (llGetInventoryNumber(INVENTORY_TEXTURE) > iNumberTextures)
          { //Es gibt eine neue Textur.
            kTexture = llGetInventoryKey(llGetInventoryName(INVENTORY_TEXTURE, llGetInventoryNumber(INVENTORY_TEXTURE)-1)); //Den Key der zuletzt eingefügten Textur auslesen.
            llSetTexture(kTexture, iTextureFace); //Die 'neue' Textur verwenden (falls jemand mit Modify-Permissions das Inventar verändert hat, wird die zuletzt eingefügte Textur verwendet).
          } //else: nichts tun.
        }
      }
    }
    
    PS: Dieses Skript nimmt immer die zuletzt eingefügte Textur (was ja schließlich gefragt war), und belässt die vorhandenen im Inventar (man kann problemlos hunderte Texturen im Objekt-Inventar lassen, das stört das Skript nicht).
     
    Zuletzt bearbeitet: 15. Februar 2014
  8. Kelith Resident

    Kelith Resident Aktiver Nutzer

    Beiträge:
    318
    Zustimmungen:
    2
    Punkte für Erfolge:
    0
    Ich probiere das gleich mal aus. Nach meinen Informationen liest llGetInventoryName das Inventar aber alphabetisch, nicht chronologisch. Man erhält mit der oben beschriebenen Methode die Textur, die nach dem Alphabet die letzte ist, nicht zwangsläufig die Textur, die man zuletzt eingefügt hat.
     
  9. Kelith Resident

    Kelith Resident Aktiver Nutzer

    Beiträge:
    318
    Zustimmungen:
    2
    Punkte für Erfolge:
    0
    @Jenna,
    Du löscht eine Textur aus dem Invantar, nachdem Du diese auf eine Fläche gelegt hast.
    Code:
    [COLOR=#333333]while (name != "")
    [/COLOR]{
          llSetTexture(name, 1);
          llRemoveInventory(name);
          name =  llGetInventoryName(INVENTORY_TEXTURE, 0);
    [COLOR=#333333]}[/COLOR]
    Wie ich nun feststelle, wird dadurch auch die Fläche wieder ohne diese Textur dargestellt, so wie sie zuvor war.
    Schlussfolgerung: Wenn man eine Textur im Inventar hat und über deren Namen oder auch UUID (selber getestet) einer Fläche zuweist und dann diese Textur aus dem Inventar entfernt, ist auch die Fläche wieder wie vorher. So, als wäre nichts geschehen.
    Darauf wiederrum folgt, die benutzte Textur muss im Inventar verbleiben, nur die anderen Texturen (falls mehrere gleichzeitig gedropt werden) können weg.

    Was mich auf das nächste Problem bringt.
    Wenn man mehrere Texturen zugleich in das Objekt dropt, läuft das Skript schon mal los, obwohl noch Texturen ins Inventar kommen. Das kann man so kaum vernünftig handhaben. Besonders, weil die Texturen alphabetisch sortiert werden und man ja nie weiß, was da an Texturen noch reinflattert. Wenn man 20 Texturen markiert und zugleich ins Objekt fallen läßt, gehts das drunter und drüber.
     
  10. Kelith Resident

    Kelith Resident Aktiver Nutzer

    Beiträge:
    318
    Zustimmungen:
    2
    Punkte für Erfolge:
    0
    Ein stabiles Verhalten und Aufräumen des Inventars bei vielen gedropten Texturen bekomme ich so hin: Mit einer 5 sekündigen Pause nach dem CHANGE. Aber 20 Texturen brauchen länger (eben getestet) als 5 Sekunden, bis sie im Inventar des Objekts erscheinen. Das Skript kommt damit aber klar, es werden nur ggf. zwei oder drei Texturen nacheinander angezeigt. Doof ist die Pause schon, ich sehe ungeduldige Anwender vor mir.:wink:

    Code:
    string  name;default
    {
     state_entry()
        {
             llAllowInventoryDrop(TRUE);                        // Das Ablegen von Inventar erlauben.
             name =  llGetInventoryName(INVENTORY_TEXTURE, 0);  // as default there is already one texture
    }
        changed(integer change)
        {
            if (change & (CHANGED_ALLOWED_DROP | CHANGED_INVENTORY))    // if there has been a change to the prim's contents ...
            {
                llSleep(5.0);
                if (llGetInventoryNumber(INVENTORY_TEXTURE) > 1)        // if there is another texture
                {   
                    llRemoveInventory(name);                            // remove last known texture
                    if (name = llGetInventoryName(INVENTORY_TEXTURE, 0))  llSetTexture(name,1);  // if a texture exists set it
    
    
                    while (llGetInventoryName(INVENTORY_TEXTURE, 1))
                    {
                        llRemoveInventory(llGetInventoryName(INVENTORY_TEXTURE, 1));                    
                    }
                }
            }
        }
    }
     
  11. MartinRJ Fayray

    MartinRJ Fayray Freund/in des Forums

    Beiträge:
    796
    Zustimmungen:
    2
    Punkte für Erfolge:
    18
    Oh ja stimmt - das ist ein Irrtum der mir schon mehrmals passiert ist.
    Du wirst dann wohl tatsächlich entweder die Texturen löschen müssen, oder die Namen am Ende des changed-Events in einer Liste speichern, z.B. mit dieser Funktion: list lInventoryList () { list l; integer i; for (i=0; i<llGetInventoryNumber(INVENTORY_TEXTURE); i++) {l += llGetInventoryName(INVENTORY_TEXTURE, i);} return l; }


    Und dann im Changed - Event überprüfen welche Texturen schon vorhanden sind: string getNewTexture(list l) { integer i; for (i=0; i<llGetInventoryNumber(INVENTORY_TEXTURE); i++) {if (llListFindList(l, [llGetInventoryName(INVENTORY_TEXTURE, i)]) == -1) {return llGetInventoryName(INVENTORY_TEXTURE, i);}} return "";}
    -> aufrufen mit string sTexture = getNewTexture(lGlobalInventoryList);
    und gleich danach die neue Liste global speichern: lGlobalInventoryList = lInventoryList();



    Das komplette Skript sieht dann so aus:

    EDIT: Das was du beobachtet hast, dass die Textur verschwindet, passiert sogar bei Fullperm- Texturen (gerade ausprobiert) - das hätte ich nicht gedacht! Ich war der Meinung dass Fullperm-Texturen nicht von der Prim-Oberfläche verschwinden wenn sie aus dem Objekt-Inventar entfernt werden (natürlich reden wir hier von Texturen die mit llSetTexture zusammen verwendet wurden).
     
    Zuletzt bearbeitet: 15. Februar 2014
  12. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.993
    Zustimmungen:
    66
    Punkte für Erfolge:
    64
    Und ich dachte das passiert nur wenn die einer Oberfläche zugewiesene Textur manuell aus dem Objektinventar gelöscht wird. Dann erscheint da wieder die Holztextur laut meiner Beobachtung.

    Wenn es so ist, dann muss man die Übernommene Textur nicht löschen, nur die anderen. Oder den Key der Textur (leider Fullperm benötigt) ermitteln und diesen dann setzen, dann sollte die Textur beim löschen nicht verschsinden. Wenn doch, nach dem Löschvorgang die Textur via key erneut setzen.

    Die Texturen in Liste speichern hat den Vorteil, dass die Texturen auch bleiben. Aber dann auch den Speicher über die Liste verbrauchen. Wielange es braucht bis der Speicher überläuft, keine anung, aber ein String verbraucht in einer Liste etwa 18 Bytes + 2 Byte per Zeichen. Geht man von Namen der bilder von etwa 40 Zeichen aus (schon recht lang, aber Snapshots schreiben da alles mögliche, also sollte passen) dann nimmt jeder Name 98 Byte. 60kb reichen dann für 612 Bilder. Könnte also reichen.
     
  13. MartinRJ Fayray

    MartinRJ Fayray Freund/in des Forums

    Beiträge:
    796
    Zustimmungen:
    2
    Punkte für Erfolge:
    18
    Leider wird die Textur tatsächlich auch von der Primoberfläche entfernt, wenn man den Key verwendet. Die Textur nach dem Löschen neu auftragen ist eine praktikable Lösung, man muss dann eben den Key zwischenspeichern, und das Changed-Event überwachen um gegebenenfalls die Textur neu zu setzen (z.B. kann man im Changed-Event vergleichen ob das Face wieder die Default-Textur verwendet, und dann die zwischengespeicherte Textur nochmals auftragen).
     
  14. Daemonika Nightfire

    Daemonika Nightfire Forumsgott/göttin

    Beiträge:
    7.929
    Zustimmungen:
    1.242
    Punkte für Erfolge:
    124
    Wie waers mit der Textbox?

    Damit liesse dich das doch ohne Textur einlegen realisieren und das Object muesste nicht modify sein.

    1. Einfach mit der rechten Maustaste im Inventar die Asset-UUID kopieren,
    2. das Object clicken damit sich die Textbox per Menue oeffnet,
    3. die UUID in die Textbox einfuegen und senden,
    4. fertig.
    Wenn die Textur Fullperm ist, gibt es mit der UUID ueberhaupt keine Probleme.

    LG
    Dae
     
  15. Kelith Resident

    Kelith Resident Aktiver Nutzer

    Beiträge:
    318
    Zustimmungen:
    2
    Punkte für Erfolge:
    0
    Danke nochmal für die vielen guten Vorschläge. Listen zu führen geht mir ehrlich gesagt dann doch zu weit für so ein simples Teil. Mein hier zuletzt gepostetes Skript funktioniert ganz ordendlich. Es wird stumpf die (alphabetisch) erste Textur übernommen bzw. durch eine andere ersetzt. Wer mehr als eine Textur reinschiebt, weiß eh nicht, was er tut, und die fliegen dann alle wieder raus bis auf eine. Bei so Masseninserts ist das Skript schneller als die Objekte ins Inventar plumpsen, daher die 5 Sekunden Pause. Die 5 Sekunden zum Stabilisieren des Inventars überbrücke ich duch einen Hovertext.
    Damit das Objekt nicht zur Mülltonne verkommt, in die jeder was reinschmeißt, muss der Owner oder jemand aus der selben Gruppe das Objekt anklicken. Erst dann wird ALLOW_INVENTORY_DROP auf TRUE gesetzt und nach 15 Sekunden per Timer wieder auf FALSE.

    Das mit der Textbox habe ich auch in Erwägung gezogen und auch schon mal ausprobiert gehabt. Ist einerseits einfacher, da immer nur eine UUID übergeben werden kann und man das Inventargetue nicht braucht. Andererseits werden auch bei dieser Lösung, ebenso wie bei meiner, Anwender da stehen und nicht wissen, was genau zu tun ist. Ich weiß auch nicht, ob alle Viewer einen Rechtsklick mit der Option Asset-UUID abbieten. Kurz gesagt, jede Lösung hat ihre Vor- und Nachteile.

    Das mit dem Löschen einer Textur aus dem Objektinventar ist schon witzig. Ich habe das Objekt normal texturiert, also über das Baumenü eine Textur aus meinem Inventar gewählt. Die Textur war nicht im Objektinventar. So ist das Objekt dann auch wieder gespeichert in meinem Inventar. Wenn ich das Objekt wieder rezze, ist alles normal. Testweise habe ich dann mal die Textur, mit der das Objekt texturiert wurde, in das Objektinventar gelegt und dann daraus wieder gelöscht. Und zack ist das Objekt plötzlich wieder aus Sperrholz.
     

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies, um Inhalte zu personalisieren, diese deiner Erfahrung anzupassen und dich nach der Registrierung angemeldet zu halten.
    Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden