Hallo zusammen,
Weiter geht's mit dem beliebten Thema
Vollmatrix.
Bei diesem Thema habe ich zu Beginn diverse Schwierigkeiten erwartet:
- mind. 2 Schriftgrößen wie aus einem Guss aussehen lassen
- zentrieren der Schrift und trotzdem exaktes ausrichten nach dem Hintergrund (ausgeschaltete LEDs)
- Implementierung von Groß- und Kleinschreibung
Ich habe mich bereits zu Beginn dafür entschieden, den Zeichensatz mit der größeren Schrift auf eine eigene Texttextur zu legen, weil ich ansonsten auf Sonderzeichen, die mit der Tastatur nicht ohneweiteres erzeugt werden können, zurückgreifen müsste und noch dazu die Logik Schaden nehmen würde und die Koordinierung der Texturen noch komplexer wäre.
Das bedeutet für Blender, dass pro Zielanzeige drei Flächen mit Texttexturen belegt werden müssen.
Dementsprechend habe ich als benötigte Stringvariablen deklariert:
Ziel_vorne_groß
Ziel_vorne_oben
Ziel_vorne_unten
Ziel_rechts_groß
Ziel_rechts_oben
Ziel_rechts_unten
Zudem habe ich, da es im Skriptablauf erforderlich wurde, Strings kurzzeitig zu speichern, zusätzlich 3 Stringregister als lokale Stringvariablen definiert:
StringRegist0
StringRegist1
StringRegist2
Die Matritzen für vorne und rechts sind deshalb getrennt, weil ich auf der Seite testhalber die Liniennummer weggelassen habe.
Grundsätzlich ist im folgenden eine Funktion beschrieben, die durch eine Änderung des Zielschildes aufgerufen wird und sollte deshalb auch als Macro definiert werden.
Schritt 1: Laden der Endhaltestellenstring
(L.L.Bediengeraet_akt_Ziel) (M.V.GetTerminusIndex) s0
l0 (S.L.target_index_int)
l0 1 (M.V.GetTerminusString) (S.$.StringRegist0)
l0 2 (M.V.GetTerminusString) (S.$.StringRegist1)
Soweit, so klar. Als Hintergrundinformation: Die Liniennummer ist in meinem Beispiel als (L.L.Bediengeraet_Linie) gespeichert.
Als nächstes kommt das wirklich aufwändige: Das Aufbereiten der Strings, um sie im Anschluss als Texttexturen auszugeben.
Da nach Möglichkeit eine Kompatibilität zu den bestehenden HOF-Files gewährleistet werden sollte und diese zur Darstellung auf den Zielanzeigen von SD und D Leerzeichen enthalten, die bei der Zentrierung stören könnten, müssen diese unnötigen Leerzeichen am Anfang und Ende des Strings als erstes entfernt werden.
Da dies nicht nur mit einem String passieren muss, habe ich das in ein eigenes Macro ausgelagert.
Das Macro entfernt immer die Leerzeichen im String (L.$.StringRegist0), also muss ein bisschen was herumgeschoben werden
Im Anschluss das Macro gekürzt wiedergegeben. Im Code empfehle ich, die ifs bis zur Länge 1 weiterzuführen.
- Spoiler:
{macro:CutLeerzeichen}
' Angenommen wird eine maximale Stringlänge von 20 Zeichen
' Zum Vergleich: Die ANNAX des D92 bietet nur Platz für 16 Zeichen
' Als erstes von links kürzen
(L.$.StringRegist0) 20 $SetLengthL (S.$.StringRegist0) 1 $SetLengthL " " $=
{if}
(L.$.StringRegist0) 19 $SetLengthR (S.$.StringRegist0) 1 $SetLengthL " " $=
{if}
(L.$.StringRegist0) 18 $SetLengthR (S.$.StringRegist0) 1 $SetLengthL " " $=
{if}
(L.$.StringRegist0) 17 $SetLengthR (S.$.StringRegist0) 1 $SetLengthL " " $=
{if}
(L.$.StringRegist0) 16 $SetLengthR (S.$.StringRegist0) 1 $SetLengthL " " $=
...
{endif}
{endif}
{endif}
{endif}
' Und kürzen von rechts
(L.$.StringRegist0) 20 $SetLengthL (S.$.StringRegist0) 1 $SetLengthR " " $=
{if}
(L.$.StringRegist0) 19 $SetLengthL (S.$.StringRegist0) 1 $SetLengthR " " $=
{if}
(L.$.StringRegist0) 18 $SetLengthL (S.$.StringRegist0) 1 $SetLengthR " " $=
{if}
(L.$.StringRegist0) 17 $SetLengthL (S.$.StringRegist0) 1 $SetLengthR " " $=
{if}
(L.$.StringRegist0) 16 $SetLengthL (S.$.StringRegist0) 1 $SetLengthR " " $=
{if}
(L.$.StringRegist0) 15 $SetLengthL (S.$.StringRegist0) 1 $SetLengthR " " $=
...
{endif}
{endif}
{endif}
{endif}
{endif}
{end}
Das Macro ist für beide Zielschild-Strings (oben und unten) auszuführen.
Als nächstes kann ermittelt werden, ob die Matrix in den Ein- oder Zweizeilenmodus "geschaltet" wird:
' Ausgabe an der Zielanzeige EIN- oder ZWEI-zeilig?
(L.$.Bediengeraet_Ziel_oben) " " $=
(L.$.Bediengeraet_Ziel_unten) " " $= ||
{if}
' EINzeilige Ausgabe
{else}
' ZWEIzeilige Ausgabe
{endif}
Im Falle der Einzeiligen Ausgabe werden als erstes alle Strings, die in der kleinen Schriftgröße dargestellt würden mit dem Leerstring "" überschrieben.
Zudem muss ermittelt werden, ob nun die obere oder untere Zeile ausgegeben werden soll:
(L.$.Bediengeraet_Ziel_oben) " " $=
{if}
(L.$.Bediengeraet_Ziel_unten) (S.$.Ziel_vorne_groß)
{else}
(L.$.Bediengeraet_Ziel_oben) (S.$.Ziel_vorne_groß)
{endif}
Durch das Macro CutLeerzeichen werden alle Strings, die nur aus Leerzeichen bestehen auf ein einzelnes Leerzeichen gekürzt und alle Leerstrings werden durch ein einfaches Leerzeichen ersetzt. Dadurch kann mit einem einfachen Leerzeichen überprüft werden, welcher der Strings angezeigt werden muss.
Um den Zieltext korrekt zentrieren zu können, muss als erstes die Liniennummer hinsichtlich ihrer Breite in Matrixpunkten untersucht werden.
Wenn die Liniennummer 0 ist, kann man sich die Ermittlung sparen, ansonsten habe ich mich dazu entschlossen, die Berechnung der Breite wieder auszulagern.
Hierzu gibt es wieder ein Macro, das mit den benötigten Parametern via (String-)Register versorgt wird.
(M.L.StringlengthPunkte_groß)
' Input-Variablen: StringRegist0 (String, von dem die Länge in Punkten zu ermitteln ist)
' Arbeits-Variablen: Register 0 (Länge des Strings in Zeichen)
' StringRegist1 (aktuell betrachtetes Zeichen)
' Output-Variablen: Register 1 (Länge des Strings in Punkten)
Das Macro ermittelt die Breite/Länge des Strings in Matrixpunkten, es addiert also die Längen aller Zeichen im String. Um zu wissen, wie breit die Zeichen sind, ist im Script für jedes darstellbares Zeichen die Punktbreite in der Form
- Spoiler:
0 s1
(L.$.StringRegist0) $length s0
' Als erstes Isolieren des zu untersuchenden Zeichens
(L.$.StringRegist0) 1 $SetLengthL 1 $SetLengthR
(S.$.StringRegist1) "A" $=
(L.$.StringRegist1) "B" $= ||
(L.$.StringRegist1) "C" $= ||
(L.$.StringRegist1) "D" $= ||
(L.$.StringRegist1) "G" $= ||
(L.$.StringRegist1) "H" $= ||
(L.$.StringRegist1) "J" $= ||
(L.$.StringRegist1) "K" $= ||
(L.$.StringRegist1) "O" $= ||
(L.$.StringRegist1) "P" $= ||
(L.$.StringRegist1) "Q" $= ||
(L.$.StringRegist1) "R" $= ||
(L.$.StringRegist1) "S" $= ||
(L.$.StringRegist1) "T" $= ||
(L.$.StringRegist1) "U" $= ||
(L.$.StringRegist1) "V" $= ||
(L.$.StringRegist1) "Y" $= ||
(L.$.StringRegist1) "Z" $= ||
(L.$.StringRegist1) "Ä" $= ||
(L.$.StringRegist1) "Ö" $= ||
(L.$.StringRegist1) "Ü" $= ||
(L.$.StringRegist1) "a" $= ||
(L.$.StringRegist1) "b" $= ||
(L.$.StringRegist1) "c" $= ||
(L.$.StringRegist1) "d" $= ||
(L.$.StringRegist1) "e" $= ||
(L.$.StringRegist1) "g" $= ||
(L.$.StringRegist1) "h" $= ||
(L.$.StringRegist1) "j" $= ||
(L.$.StringRegist1) "n" $= ||
(L.$.StringRegist1) "o" $= ||
(L.$.StringRegist1) "p" $= ||
(L.$.StringRegist1) "q" $= ||
(L.$.StringRegist1) "s" $= ||
(L.$.StringRegist1) "u" $= ||
(L.$.StringRegist1) "x" $= ||
(L.$.StringRegist1) "y" $= ||
(L.$.StringRegist1) "ä" $= ||
(L.$.StringRegist1) "ö" $= ||
(L.$.StringRegist1) "ü" $= ||
(L.$.StringRegist1) "ß" $= ||
(L.$.StringRegist1) "0" $= ||
(L.$.StringRegist1) "2" $= ||
(L.$.StringRegist1) "3" $= ||
(L.$.StringRegist1) "4" $= ||
(L.$.StringRegist1) "5" $= ||
(L.$.StringRegist1) "6" $= ||
(L.$.StringRegist1) "7" $= ||
(L.$.StringRegist1) "8" $= ||
(L.$.StringRegist1) "9" $= ||
l0 1 >= &&
{if}
l1 7 + s1
{endif}
(L.$.StringRegist1) "E" $=
(L.$.StringRegist1) "F" $= ||
(L.$.StringRegist1) "L" $= ||
(L.$.StringRegist1) "f" $= ||
(L.$.StringRegist1) "k" $= ||
(L.$.StringRegist1) "r" $= ||
(L.$.StringRegist1) "t" $= ||
(L.$.StringRegist1) "z" $= ||
l0 1 >= &&
{if}
l1 6 + s1
{endif}
(L.$.StringRegist1) "M" $=
(L.$.StringRegist1) "N" $= ||
(L.$.StringRegist1) "X" $= ||
(L.$.StringRegist1) "v" $= ||
(L.$.StringRegist1) "w" $= ||
l0 1 >= &&
{if}
l1 8 + s1
{endif}
(L.$.StringRegist1) "I" $=
(L.$.StringRegist1) "i" $= ||
l0 1 >= &&
{if}
l1 3 + s1
{endif}
(L.$.StringRegist1) "W" $=
l0 1 >= &&
{if}
l1 10 + s1
{endif}
(L.$.StringRegist1) "m" $=
l0 1 >= &&
{if}
l1 9 + s1
{endif}
(L.$.StringRegist1) "l" $=
(L.$.StringRegist1) "-" $= ||
l0 1 >= &&
{if}
l1 5 + s1
{endif}
(L.$.StringRegist1) " " $=
(L.$.StringRegist1) "." $= ||
l0 1 >= &&
{if}
l1 2 + s1
{endif}
hinterlegt.
Das Macro ist etwas komplexer geworden, da das OMSI-Script keine Schleifen gestattet. Da ich in letzter Zeit viel mit php zu tun hatte und deshalb noch einen entsprechenden Präprozessor auf meinem Rechner installiert habe, habe ich mich entschieden, die Schleife in php zu realisieren und das ausgegebene Ergebnis in die osc-Datei zu kopieren. Das gleiche sollte aber mit jeder anderen Programmier oder Skriptsprache funktionieren, die Schleifen unterstützt und das Ergebnis in einer Form ausgeben kann, das Copy&Paste-fähig ist.
Ein ähnliches Macro gibt es noch einmal für die kleinere Schriftgröße.
Nach jedem Macro, das Werte zurückgibt, ist es wichtig, diese Werte sofort in Variablen zu schreiben, die vom weiteren Ablauf erst wieder verändert werden, wenn die Werte nicht mehr gebraucht werden!
Im Anschluss wird die LEDPunkteLänge des Zieltextes wieder mit dem Macro ermittelt.
Zum Abschluss wird der String zusammengebaut, der dann am Zielschild angezeigt wird.
' //Matrixlänge (121) - LN-Länge = Platz für Ziel
' //(Platz für Ziel - Länge Zielstring) / 4 = aufzufüllende Leerzeichen
121 (L.L.Matrix_Laenge_oben) - l1 - 4 / s2
"<" (L.$.StringRegist2) $+ " " l2 $* $+ (L.$.StringRegist0) $+ " " l2 $* $+ " " $+ (S.$.Ziel_vorne_groß)
121 l1 - 4 / s2
"<" " " l2 $* $+ (L.$.StringRegist0) $+ " " l2 $* $+ " " $+ (S.$.Ziel_rechts_groß)
Rechts wird wiederum extra behandelt, weil da keine Liniennummer angezeigt wird.
Für die zweizeilige Ausgabe gilt im Grunde das selbe, nur dass eben die Variablennamen zum Teil anders sind und ein Teil einmal für oben und einmal für unten auszuführen ist.
Hiermit bin ich vorerst am Ende meines bereits vorhandenen Codes. In naher Zukunft möchte ich mich mit dem Thema FSD (Fahrscheindrucker) beschäftigen. Hierzu muss ich noch ein paar Skizzen des Originals anfertigen. Ich möchte versuchen, den Zelisko FSD4R umzusetzen und im Anschluss darüber einen Fahrzeuginternen DFI-Monitor mit Haltestellenvorschau anzusteuern.
Sollte ich mich irgendwo missverständlich ausgedrückt haben, oder wenn Fragen auftauchen, einfach posten.
Schönen Abend noch,
Busfanat
P.S.: @Mods: Sry für Doppelpost, wollte die Kapitel einfach trennen. Wenn nicht erwünscht, bitte Posts zusammenfassen.
EDIT, 19.11.11:
Hallo zusammen,
gestern habe ich als Antwort auf diesen Post eine E-Mail vom Nutzer "Flopsi" erhalten, welche ich hier beantworten möchte. Ich habe von ihm die Erlaubnis bekommen, diese Mail hier zu zitieren:
- Zitat :
- Flopsi schrieb (per E-Mail):
N'abend Busfanat,
ich habe mich gerade mal durch deinen Beitrag gelesen, in dem du über das Scripten einer Vollmatrix schreibst.
Ich wüsste gern, in wie fern diese Scripts einzufügen sind. Ich habe mich gerade darin versucht, diese Schnipsel zu verwenden, doch ich erhalte nur Fehlermeldungen.
Ist es nötig neue Dateien zu erstellen oder die Vorhandenen nur zu ändern?
Ich finde es auf jeden Fall super, dass du dich damit beschäftigt und wie es aussieht auch verstanden hast.
Bedanke mich schonmal im Voraus für eine Atnwort und wünsch erstmal noch einen schönen Abend.
Gruss
Flopsi
Meine Skripts sind nicht für bestehende Busse entwickelt sondern für Modder gedacht, die neue Fahrzeuge erstellen. Aus diesem Grunde stimmen z.B. auch die Variablennamen nicht mit denen der mitgelieferten Busse überein.
Für jede Matrixanzeige sind vier Texturen nötig. Eine Hintergrundtextur, die alle LEDs in "Aus" darstellt, eine Texttextur für die "große" Schriftart, mit der die LN- Nummer und der Text eines einzeiligen Ziels angezeigt wird und zwei Texttexturen für die "kleine" Schriftart, mit der die Texte eines zweizeiligen Ziels angezeigt werden, einmal oben und einmal unten. Die Größe der Texturen ist von den verwendeten Schriften abhängig.
Danke für dein Kompliment, dass ich es verstanden hätte. Ich habe in der letzten Zeit in unterschiedlichen Programmiersprachen Einführungen genossen und kann mich relativ schnell in neue Syntaxen einarbeiten. Allerdings bin ich mir sicher, dass sich vor allem der Code für die Matrix noch optimieren, sprich kürzen, lässt.
Sollte jemand die Code-Teile einsetzen wollen, bin ich gerne bereit, beim Einsetzen der Codes zu helfen.
mfG,
Busfanat