Dieses Tutorial beschreibt, wie einzelne Objekte automatisiert mit dem Graph::Aligner
Knoten ausgerichtet werden können.
ContainerAlignment
Ganz generell und unabhängig vom Aligner
Graphenknoten kann bei einigen Objekten (wie etwa PlaneGeometry
oder TextGeometry
) der Ankerpunkte für die Positionierung mit den Attributen containerAlignmentX
und containerAlignmentY
angepasst werden. Standardmäßig liegt der Ankerpunkt immer im Zentrum.
Die gültigen Werte sind im Enum IEnums::AlignmentX
bzw. IEnums::AlignmentY
aufgelistet:
UNDEFINED
LEFT
(oderBOTTOM
für Y)CENTER
(default)RIGHT
(oderTOP
für Y)NEGATIVE
POSITIVE
Zur Veranschaulichung positionieren wir drei Planes an derselben Position 0/0/0 und ändern lediglich die Parameter containerAlignmentX
und containerAlignmentY
(sowie den Farbparameter).
<!-- blue plane --> <PlaneGeometry id="box_plane_01" posX="0" posY="0" scaleFactor="100" parametersSlot="0" materialSlot="2"/> <!-- red plane --> <PlaneGeometry id="box_plane_02" posX="0" posY="0" scaleFactor="100" parametersSlot="1" materialSlot="2" containerAlignmentX="LEFT" containerAlignmentY="TOP"/> <!-- green plane --> <PlaneGeometry id="box_plane_03" posX="0" posY="0" scaleFactor="100" parametersSlot="2" materialSlot="2" containerAlignmentX="RIGHT" containerAlignmentY="BOTTOM"/>
Als Ergebnis erhalten wir drei Planes die entsprechend ihren Alignment-Vorgaben unterschiedlich positioniert werden. Alle drei Planes haben die gleiche Ankerposition in der virtuellen Welt (0/0/0), allerdings liegt der Ankerpunkt bei der blauen Plane im Zentrum, bei der roten links oben und bei der grünen rechts unten.
Aligner Graphenknoten
Der Aligner
Graphenknoten kann verwendet werden um Objekte entlang einer vorgegebenen Achse automatisch anordnen zu lassen. Dabei berechnet der Aligner
Knoten für alle seine direkten Kindknoten (bzw. Sub-Graphen) die entsprechende Container-Größe und ordnet sie nacheinander an. Als erstes Beispiel ordnen wir drei PlaneGeometry
-Objekte entlang der Y-Achse an.
<Aligner id="aligner01" axis="Y" posX="-200" > <!-- blue plane --> <PlaneGeometry scaleFactor="100" parametersSlot="0" materialSlot="2"/> <!-- red plane --> <PlaneGeometry scaleFactor="100" parametersSlot="1" materialSlot="2" containerAlignmentX="LEFT" containerAlignmentY="TOP"/> <!-- green plane --> <PlaneGeometry scaleFactor="100" parametersSlot="2" materialSlot="2" containerAlignmentX="RIGHT" containerAlignmentY="BOTTOM"/> </Aligner>
Das Zentrum des Aligner
Knoten legen wir nach links an die Position -200/0/0. Die PlaneGeometry
Objekte werden entlang der Y-Achse des Aligners angeordnet. Die anderen Koordinatenwerte (X/Z) bleiben unverändert.
Mit dem Attribut objectAlignment
können auch die Koordinatenwerte der verbleibenden Achsen (in unserem Fall X/Z) angepasst werden. Beispielsweise bewirkt die Angabe objectAlignmentX="LEFT"
, dass alle Objekte entlang des linken Rands des Aligners ausgerichtet werden.
Zur Veranschaulichung erstellen wir einen neuen Aligner
Knoten, bei dem das Attribut objectAlignmentX
gesetzt ist. Durch die Angabe von posY="150"
und containerAlignmentY="TOP"
wird der obere Rand des Aligner
an die Position 150
gelegt. Die Angabe von order="DESCENDING"
bewirkt eine absteigende Anordnung.
<Aligner id="aligner02" axis="Y" posX="-350" posY="150" containerAlignmentY="TOP" objectAlignmentX="LEFT" order="DESCENDING"> <!-- blue plane --> <PlaneGeometry scaleFactor="100" parametersSlot="0" materialSlot="2"/> <!-- red plane --> <PlaneGeometry scaleFactor="100" parametersSlot="1" materialSlot="2" containerAlignmentX="LEFT" containerAlignmentY="TOP"/> <!-- green plane --> <PlaneGeometry scaleFactor="100" parametersSlot="2" materialSlot="2" containerAlignmentX="RIGHT" containerAlignmentY="BOTTOM"/> </Aligner>
Mit dem Attribut spacing
kann ein Abstand zwischen den angeordneten Objekten definiert werden und mit dem Attribut padding
kann ein äußerer Rand für den Aligner
festgelegt werden.
<Aligner id="aligner03" axis="Y" posX="250" posY="250" containerAlignmentY="TOP" containerSizeX="200" order="DESCENDING" spacing="20"> <TextGeometry materialSlot="4" systemFontName="SansBold" fontSize="20" textColor="255i, 255i, 255i, 255i" backgroundColor="0i, 0i, 0i, 0i" text="Line 1 centered" enableWordWrapping="yes" containerSizeX="200" textAlignmentX="CENTER" /> <TextGeometry materialSlot="4" systemFontName="SansBold" fontSize="20" textColor="255i, 255i, 255i, 255i" backgroundColor="0i, 0i, 0i, 0i" text="A auto wrapped text line" enableWordWrapping="yes" containerSizeX="200" textAlignmentX="CENTER" /> <TextGeometry materialSlot="4" systemFontName="SansBold" fontSize="20" textColor="255i, 255i, 255i, 255i" backgroundColor="0i, 0i, 0i, 0i" text="A manually wrapped line" enableWordWrapping="yes" containerSizeX="200" textAlignmentX="CENTER" /> <TextGeometry materialSlot="4" systemFontName="SansBold" fontSize="20" textColor="255i, 255i, 255i, 255i" backgroundColor="0i, 0i, 0i, 0i" text="Left aligned text" enableWordWrapping="yes" containerSizeX="200" textAlignmentX="LEFT" /> <TextGeometry materialSlot="4" systemFontName="SansBold" fontSize="20" textColor="255i, 255i, 255i, 255i" backgroundColor="0i, 0i, 0i, 0i" text="Right aligned text" enableWordWrapping="yes" containerSizeX="200" textAlignmentX="RIGHT" /> <Node> <PlaneGeometry scaleFactor="100" parametersSlot="0" materialSlot="2" containerAlignmentY="TOP"/> <PlaneGeometry scaleFactor="100" parametersSlot="1" materialSlot="2" containerAlignmentX="LEFT" /> <PlaneGeometry posX="25" posY="-25" scaleFactor="100" parametersSlot="2" materialSlot="2" containerAlignmentX="RIGHT" containerAlignmentY="BOTTOM"/> </Node> </Aligner>
Die resultierende Größe des Aligner
nach dem Anordnen kann mit der Methode GetBoundingVolume()
abgefragt werden. Allerdings muss die Abfrage in der Methode OnFinishTick()
und nicht in der Methode OnProcessTick()
erfolgen, da das Ausrichten der Objekte im Aligner
erst nach erfolgter Abarbeitung von OnProcessTick()
durchgeführt wird. Eine Abfrage in OnProcessTick()
liefert daher immer die Werte des vorherigen Frames.
void App::AlignerLogic::OnFinishTick(const Logic::IState* state) { // Size if (mPrintBoundingValues) { const Graph::IBoundingVolume* boundingVolume = mAligner->GetBoundingVolume(); const Graph::Box& box = boundingVolume->GetInnerLocalBox(); const Graph::Vector& min = box.GetMinimum(); const Graph::Vector& max = box.GetMaximum(); Debug::Trace("From OnFinishTick:"); Debug::Trace(" Bounding X %f / %f", min.x, max.x); Debug::Trace(" Bounding Y %f / %f", min.y, max.y); Debug::Trace(" Bounding Z %f / %f", min.z, max.z); mPrintBoundingValues = false; } }
Als Ergebnis erhalten wir für den Aligner
aligner03
und das erste Frame:
Für alle weiteren Frames liefert OnProcessTick()
und OnFinishTick()
dasselbe Ergebnis, da sich in unserem Beispiel die Inhalte des Aligner
nicht mehr ändern und damit das IBoundingVolume
gleich bleibt. Durch Drücken der Taste P kann das IBoundingVolume
für ein weiteres Frame ausgegeben werden:
Wir können das berechnete IBoundingVolume
noch optisch mit einem PlaneGeometry
Knoten verifizieren:
<PlaneGeometry posX="250" posY="250" containerAlignmentY="TOP" scaleFactorX="200" scaleFactorY="450" parametersSlot="3" materialSlot="2" depthOrder="-1" />