X-Friese 34 Posted August 29, 2015 Share Posted August 29, 2015 FlyWithLua hat im Laufe seiner mehrjährigen Entwicklung verschiedene Verfahren hervorgebracht, wie auf DataRefs (also X-Planes interne Variablen) zugegriffen werden kann. Diese sind aber unterschiedlich komplex in der Abarbeitung durch den Lua Kern. Betrachten wir ein Beispiel.Wir möchten die Sichtweite in Abhängigkeit der Flughöhe steuern. Sind wir zu nah am Boden und haben eine zu große Sichtweite, dann gehen die FPS in den Keller. Also soll die Sichtweite je nach Höhe automatisch eingestellt werden. Die langsamste Variante wäre diese:function set_visibility() if get("sim/cockpit2/gauges/indicators/altitude_ft_pilot") < 5000 then set( "sim/weather/visibility_reported_m", 15000 ) end if get("sim/cockpit2/gauges/indicators/altitude_ft_pilot") < 10000 and get("sim/cockpit2/gauges/indicators/altitude_ft_pilot") > 5000 then set( "sim/weather/visibility_reported_m", 25000 ) end if get("sim/cockpit2/gauges/indicators/altitude_ft_pilot") > 10000 then set( "sim/weather/visibility_reported_m", 50000 ) end end do_every_frame("set_visibility()")Die Funktionen get() und set() schauen zunächst nach einer Speicheradresse, wo sich das DataRef verbirgt. Dazu übergeben sie den String an die Suchfunktion des X-Plane SDK. Diese Suchfunktion ist aber sehr langsam in der Ausführung. Unser Script sorgt nun dafür, dass diese überaus langsame Suche bei jedem Frame fünf mal ausgeführt wird (vier mal über get() und ein set() Aufruf). Wenn die Funktionen get() und set() dann die Speicherstelle kennen, lesen sie den Wert von dort aus oder schreiben sie den Wert dorthin.Das geht aber auch viel schneller, wenn man die Ermittlung der Speicherstelle einmalig beim Laden der Scripte durchführt und den Wert somit nur einmal suchen lässt. Also etwa wie folgt:-- Speicheradresse ermitteln local alt_mempos = XPLMFindDataRef("sim/cockpit2/gauges/indicators/altitude_ft_pilot") local vis_mempos = XPLMFindDataRef("sim/weather/visibility_reported_m") function set_visibility() -- Wertevariablen erzeugen local alt_value = XPLMGetDataf(alt_mempos) local vis_value = 50000 -- Logik ausführen if alt_value < 5000 then vis_value = 15000 end if alt_value < 10000 and alt_value > 5000 then vis_value = 25000 end -- Wert für Sichtweite an X-Plane übergeben XPLMSetDataf(vis_mempos, vis_value) end do_every_frame("set_visibility()")DataRefs haben unterschiedliche Datentypen. Unsere beiden sind vom Typ float, daher nutzen wir XPLMGetDataf() und XPLMSetDataf(). Den Typ kann man aus der offiziellen Tabelle entnehmen:http://www.xsquawkbox.net/xpsdk/docs/DataRefs.htmlDas ist aber viel zu kompliziert? Auf Datentypen achten, was ist das den? Klar hat FlyWithLua hier eine elegantere Lösung bekommen, die aber genau das gleiche macht:-- DataRef-Variablen erzeugen dataref("alt_value", "sim/cockpit2/gauges/indicators/altitude_ft_pilot", "readonly") dataref("vis_value", "sim/weather/visibility_reported_m", "writable") function set_visibility() vis_value = 50000 if alt_value < 5000 then vis_value = 15000 end if alt_value < 10000 and alt_value > 5000 then vis_value = 25000 end end do_every_frame("set_visibility()")FlyWithLua macht bei der Abarbeitung folgendes. Alle Variablen, die über die Funktion dataref() an ein DataRef gebunden sind, werden vor Ausführung mit den Werten aus X-Plane gefüllt. In diesem Fall würde jeweils ein XPLMGetDataf() für alt_value und vis_value ausgeführt. Ist der Code für das Frame angearbeitet, so werden alle verbundenen Variablen, die den Parameter "writable" besitzen, an X-Plane zurück geschrieben. Hier im Beispiel ist es nur ein Schreibvorgang für vis_value.Das geht ebenfalls super schnell, aber ohne das komplizierte Drumherum mit den Datentypen. Darum kümmert sich FlyWithLua. Klever, nicht wahr?Nein, das ist nur so lange klever, wie ein Script Author alle seine Scripte selbst erzeugt und pflegt. Denn wenn zwei Scripte auf das selbe DataRef schreiben wollen, geht diese Methode nicht mehr. Es würde immer nur das zuletzt schreibende gewinnen. Daher gibt es für Nutzer, die ihre Scripte mit anderen teilen wollen, eine neuere Methode, die magischen Tabellen.Lua hat als Scriptsprache eine interessante Besonderheit. Man kann in Lua magische Tabellen erzeugen. Das sind Objekte, die sich wie Tabellen zeigen und als Tabellen angesprochen werden, die aber beim Setzen oder Lesen eines Tabellenwertes eine definierbare Schreib- oder Lesefunktion ausführen. Auch das ist in FlyWithLua elegant genutzt.Wir definieren einfach alle Variablen, die wir an ein DataRef koppeln wollen, als magische Tabelle. In der Tabelle wird dann die Speicheradresse vorgehalten und je nach Datentyp wird direkt in X-Plane hinein geschrieben oder direkt aus X-Plane gelesen. Das ist von der Geschwindigkeit etwas langsamer als die Methode über die Funktion dataref(), aber erheblich schneller als get() oder set().Die neue Funktion heißt dataref_table() und wird so genutzt:-- magische Tabellen erzeugen alt_value = dataref_table("sim/cockpit2/gauges/indicators/altitude_ft_pilot") vis_value = dataref_table("sim/weather/visibility_reported_m") function set_visibility() vis_value[0] = 50000 if alt_value[0] < 5000 then vis_value[0] = 15000 end if alt_value[0] < 10000 and alt_value[0] > 5000 then vis_value[0] = 25000 end end do_every_frame("set_visibility()")Das hat den großen Vorteil, dass wir nun auch DataRef-Arrays sehr einfach als Tabelle ansprechen können. Es hat aber auch den Nachteil, dass wir nun alle DataRefs als Tabelle ansprechen müssen. Daher sind Einzelwerte (egal ob integer, float oder double) immer als Tabellenelement Nr. 0 (Null) anzusprechen. Im Script steht also immer alt_value[0] statt alt_value. Macht man das nicht stürzt das Script ab.Wenn man Scripte mit anderen teilen möchte, dann sollte man ausschließlich über die magischen Tabellen auf X-Planes DataRefs zugreifen!Wer nur für sich allein FlyWithLua verwendet, der kann natürlich auch die (historisch ältere) Methode über die Funktion dataref() wählen. Die Funktionen set() und get() sollte man dann verwenden, wenn die Ausführung nur einmalig passiert. Daher schlägt FlyWithLua in der Vorlage für die Settings (Datei ".../X-Plane 10/Resources/plugins/FlyWithLua/initial_assignments.txt") auch set() zum einmaligen Setzen der Werte vor.Anmerkung: Das Beispiel dient nur als Beispiel. Wie sinnvoll es ist die Sichtweite mit diesen Werten zu regeln sollte hier nicht diskutiert werden.Man könnte natürlich statt do_every_frame() auch do_sometimes() nutzen. Das wäre klüger, da die Höhe sich ja nicht so rasant ändert, und es nicht wichtig ist ob wir unverzüglich oder maximal zehn Sekunden später anpassen (do_sometimes() wird alle 10 Sekunden angetriggert, do_often() sekündlich). Hier ist der große Vorteil dann auch bei der neuesten Methode über dataref_table(), denn mit der Definition über dataref() hätten wir in jedem Frame trotzdem zwei Lese- und einen Schreibvorgang. Die magische Tabelle würde aber nur alle 10 Sekunden lesen und schreiben. Denn FlyWithLua prüft nicht, ob die Variablen, die über dataref() gebunden sind, überhaupt benutzt werden. Link to comment Share on other sites More sharing options...
scorpio2001de 104 Posted August 29, 2015 Share Posted August 29, 2015 Super Erklärung! Danke dafür. Link to comment Share on other sites More sharing options...
hrsoft 0 Posted August 30, 2015 Share Posted August 30, 2015 Sehr gute Erklärung, gleich ausprobiert, funktioniert super. Danke Link to comment Share on other sites More sharing options...
Othello 549 Posted January 11, 2016 Share Posted January 11, 2016 Danke X-Friese, das klingt interessant. Eine Verständnisfrage habe ich noch: Du schreibst in Bezug auf dataref() "... Es würde immer nur das zuletzt schreibende gewinnen. ...", das gilt doch auch für die dataref_table(), verstehe ich richtig, dass dataref_table() beim Ändern eines Wertes diesen sofort zurückschreibt, dataref() dagegen alle geänderten Daten verzögert am Ende (der Funktion?, von do_every_frame()?) ? Danke und Gruß Othello Link to comment Share on other sites More sharing options...
X-Friese 34 Posted January 11, 2016 Author Share Posted January 11, 2016 Ja, bei dataref() werden die Inhalte am Beginn des Frames aus X-Plane geholt und in die Lua Variablen geschrieben. Zum Ende des Frames werden dann alle "writable" Werte wieder zurück in X-Plane geschrieben. Die Funktion dataref_table() erzeugt dagegen eine magische Tabelle, die immer direkt in X-Plane schreibt oder von dort liest. Link to comment Share on other sites More sharing options...
WilKur 15 Posted April 17, 2016 Share Posted April 17, 2016 Ich habe mal eine Frage an die Fachleute, ich experimentiere mit den Wettereinstellungen in X-Plane. Gibt es eine Möglichkeit, den Button 'Read right now!' im Wettermenue 'grab real-weather from the net' in X-Plane über ein LuaScript anzusprechen bzw. gibt es dafür ein DataRef - habe leider bisher noch nichts gefunden. Gruß Willi Please login to display this image. Link to comment Share on other sites More sharing options...
jimbim 22 Posted April 18, 2016 Share Posted April 18, 2016 vor 11 Stunden , WilKur sagte: ich experimentiere mit den Wettereinstellungen in X-Plane. Gibt es eine Möglichkeit, den Button 'Read right now!' im Wettermenue 'grab real-weather from the net' in X-Plane über ein LuaScript anzusprechen bzw. gibt es dafür ein DataRef - habe leider bisher noch nichts gefunden. Hallo Willi, ich würde mal mit den Command sim/operation/regen_weather bzw. sim/operation/load_real_weather experimentieren. Kannst die ja erst mal auf eine Taste legen und schauen ob einer das macht, was Du benötigst. Wenn ja kannst Du den entsprechenden Command in deinem Script ausführen. Das war command_once() glaube ich... Bin mir aber nicht sicher. Viele Grüße, Sebastian Link to comment Share on other sites More sharing options...
WilKur 15 Posted April 18, 2016 Share Posted April 18, 2016 Hallo Sebastian, prima, danke für den Tip. Das werde ich mal ausprobieren. Gruß Willi Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.