Tutorial #12: Aligner

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 (oder BOTTOM für Y)
  • CENTER (default)
  • RIGHT (oder TOP 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).

graph_main.xml
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!-- 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.

tut0112_v1.png
containerAlignment

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.

graph_main.xml
44
45
46
47
48
49
50
51
52
53
54
<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.

tut0112_v2.png
Aligner

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.

graph_main.xml
56
57
58
59
60
61
62
63
64
65
66
67
68
<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>
tut0112_v3.png
Aligner objectAlignment

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.

graph_main.xml
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<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&#10;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>
tut0112_v4.png
Aligner spacing

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.

aligner_logic.xml
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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:

From OnProcessTick:
Bounding X 0.000000 / 0.000000
Bounding Y 0.000000 / 0.000000
Bounding Z 0.000000 / 0.000000
From OnFinishTick:
Bounding X -100.000000 / 100.000000
Bounding Y -450.000000 / 0.000000
Bounding Z 0.000000 / 0.000000

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:

From OnProcessTick:
Bounding X -100.000000 / 100.000000
Bounding Y -450.000000 / 0.000000
Bounding Z 0.000000 / 0.000000
From OnFinishTick:
Bounding X -100.000000 / 100.000000
Bounding Y -450.000000 / 0.000000
Bounding Z 0.000000 / 0.000000

Wir können das berechnete IBoundingVolume noch optisch mit einem PlaneGeometry Knoten verifizieren:

graph_main.xml
132
133
134
<PlaneGeometry posX="250" posY="250" containerAlignmentY="TOP"
                scaleFactorX="200" scaleFactorY="450"
                parametersSlot="3" materialSlot="2" depthOrder="-1" />
tut0112_v5.png
Aligner


Copyright © 2011-2025 Spraylight GmbH.