Erstellen einer 2D-Benutzeroberfläche in einer 3D-Anwendung (FireMonkey 3D-Tutorial)

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Tutorial: Erstellen einer FireMonkey 3D-Anwendung


In einer 3D-Anwendung können 2D-Komponenten, wie Schaltflächen oder Listen, nicht direkt verwendet werden. Wenn eine 2D-Komponente in einem 3D-Container abgelegt wird, wird die Komponente nicht gerendert, sondern in der Strukturansicht als untergeordnetes Steuerelement angezeigt. Es gibt aber eine einfache Möglichkeit, mit diesem Problem umzugehen, nämlich durch Erstellen einer Brücke zwischen den 3D- und den 2D-Szenen. FireMonkey stellt dafür die Komponente FMX.Layers3D.TLayer3D bereit.

Hinzufügen und Anpassen einer 2D-Oberfläche (TLayer3D) und einer Schaltfläche (TButton)

  1. Wählen Sie das Formular aus dem vorhergehenden Tutorial im Objektinspektor oder in der Strukturansicht aus, und doppelklicken Sie in der Tool-Palette auf TLayer3D.
    Layer 3D In Form.png
  2. Jetzt können Sie die TLayer3D-Komponente als Oberfläche für FireMonkey-2D-Komponenten verwenden.
    Wählen Sie in der Strukturansicht oder dem Objektinspektor die Komponente TLayer3D aus, und fügen Sie eine TButton-Komponente hinzu. Stellen Sie in der Strukturansicht sicher, dass die Schaltfläche der TLayer3D-Komponente und nicht dem Formular untergeordnet ist (wenn Sie die Hierarchie korrigieren müssen, ziehen Sie TButton auf TLayer3D).
    Layer 3D with Button In Form.png
  3. Ändern Sie den Projection-Typ der TLayer3D-Komponente, um eine 2D-Oberfläche zu simulieren. Legen Sie im Objektinspektor die folgenden Eigenschaften für die TLayer3D-Komponente fest:
    Projection = Screen
    Eine Bildschirmprojektion ist eine pixelweise Projektion auf die Bildschirmebene mit einer festen (unsichtbaren) Kamera, und die vordere Ebene des 3D-Pyramidenstumpfs ist jetzt eine Bildschirmebene. Jedes Objekt ist weiterhin 3D, kann aber wie 2D bearbeitet werden.
    Ihre 3D-Anwendung sollte jetzt so wie in der folgenden Abbildung dargestellt aussehen:
    Layer with project screen.png
  4. Wie Sie sehen, verdeckt die TLayer3D-Komponente die Szene fast vollständig. Setzen Sie im Objektinspektor folgende Eigenschaften für TLayer3D:
    • Align auf MostRight (oder eine beliebige andere Ausrichtung)
    • Width auf 150 (oder eine andere Breite in Pixel)
    Zum Beispiel:
    Aligned Layer.png

Hinzufügen und Anordnen von 2D-Komponenten

Löschen Sie nun die hinzugefügten Schaltflächen, damit Sie andere Schaltflächen hinzufügen können, mit denen die 3D-Objekte auf dem Formular gedreht und verschoben werden oder deren Größe geändert wird.

  1. Setzen Sie den Fokus auf TLayer3D, und fügen Sie fünf TGroupBox-Steuerelemente hinzu.
    1. Markieren Sie in der Strukturansicht alle Gruppenfelder, indem Sie die Taste STRG gedrückt halten und mit der Maus auf jedes Gruppenfeld klicken. Setzen Sie im Objektinspektor die Eigenschaft Align auf Top.
    2. Wählen Sie die obersten drei Gruppenfelder aus, und setzen Sie im Objektinspektor die Eigenschaft Height auf 70 (oder einen anderen Wert, der Ihnen für das endgültige Layout besser gefällt).
    3. Wählen Sie jedes TGroupBox-Steuerelement aus, und setzen Sie:
      • Text auf Width, Height, Depth, Move und Rotate
      • Name auf WidthGroupBox, HeightGroupBox, DepthGroupBox, MoveGroupBox und RotateGroupBox. Stellen Sie sicher, dass Sie die Einträge für Name und Text sich jeweils entsprechen (Width und WidthGroupBox, Height und HeightGroupBox usw.)
      • Die Eigenschaft Enabled auf False.
    4. Fügen Sie den ersten drei TGroupBox-Steuerelementen Paare von jeweils zwei Schaltflächen hinzu. Einer Schaltfläche wird zum Vergrößern und eine zum Verkleinern der Breite, Höhe und Tiefe verwendet.
      Ändern Sie die Namen der Schaltflächenpaare wie folgt:
      • IncreaseWidthButton und DecreaseWidthButton
      • IncreaseHeightButton und DecreaseHeightButton
      • IncreaseDepthButton und DecreaseDepthButton
      Ändern Sie die Eigenschaft Text entsprechend den Schaltflächennamen.
    5. Fügen Sie dem Gruppenfeld Move drei Schaltflächenpaare hinzu.
      Ändern Sie die Namen der Schaltflächenpaare wie folgt:
      • MoveRightButton und MoveLeftButton
      • MoveDownButton und MoveUpButton
      • MoveBackButton und MoveFrontButton
      Ändern Sie die Eigenschaft Text entsprechend den Schaltflächennamen.
    6. Fügen Sie dem Gruppenfeld Rotate drei TTrackBar-Komponenten hinzu, mit denen das 3D-Objekt um jede Achse gedreht wird.
    7. Ändern Sie die Namen der TTrackBar-Steuerelemente in RotateXTrackBar, RotateYTrackBar und RotateZTrackBar.
    8. Setzen Sie im Objektinspektor die Eigenschaft Min jedes Schiebereglers auf -360 und die Eigenschaft Max auf 360.
  2. Fügen Sie dem Formular eine weitere TLayer3D-Komponente hinzu.
    1. Setzen Sie im Objektinspektor die Eigenschaft Projection der neuen TLayer3D-Komponente auf Screen und die Eigenschaft Align auf Top.
    2. Fügen Sie der neuen TLayer3D-Komponente zwei TGroupBox-Steuerelemente hinzu.
    3. Wählen Sie jedes TGroupBox-Steuerelement aus, und setzen Sie:
      • Text auf Item to be Manipulated und Light On/off.
      • Name auf ManipulateItemGroupBox und LightGroupBox. Stellen Sie sicher, dass Sie die Einträge für Name und Text sich jeweils entsprechen ("Item to be Manipulated" und ManipulateItemGroupBox usw.)
    4. Fügen Sie ManipulateItemGroupBox drei TRadioButton-Steuerelemente hinzu, eins für jedes 3D-Objekt in der Szene.
    5. Wählen Sie jedes TRadioButton-Steuerelement aus, und setzen Sie:
      • Text auf Cube1, Cube2 und Light.
      • Name auf Cube1RadioButton, Cube2RadioButton und LigthRadioButton Stellen Sie sicher, dass Sie die Einträge für Name und Text sich jeweils entsprechen (Cube1 und Cube1RadioButton usw.)
    6. Fügen Sie LightGroupBox ein TButton-Steuerelement hinzu.
    7. Wählen Sie die Schaltfläche aus, und setzen Sie:
      • Text auf OFF.
      • Name auf LightOnOffButton.

Das endgültige Layout sollte wie folgt aussehen:

FinalInaterface.png

Hinzufügen von Ereignissen und Ereignisbehandlungsroutinen

Die Anwendung besteht jetzt aus einer einfachen 3D-Szene, in der Sie Objekten Ereignisse hinzufügen können.

1. Um das zu bearbeitende 3D-Objekt festzulegen, deklarieren Sie eine globale String-Variable zur Aufnahme des Objektnamens.

Im Ereignis OnChange des Schiebereglers kann das Objekt mit dem Fokus gedreht werden. Um zu vermeiden, dass die Drehwinkel des vorherigen Objekts aktualisiert werden, wenn ein anderes Objekt ausgewählt wird, fügen Sie die boolesche Variable RotateFlag hinzu. Wenn diese Variable auf False gesetzt ist, wird der Code in der Ereignisbehandlungsroutine OnChange nicht ausgelöst.

//Delphi declaration
var
  Form1: TForm1;
  ManipulatedItem: String;
  RotateFlag: boolean;
  // C++ declaration
TForm3D1 *Form3D1;
System::UnicodeString ManipulatedItem;
bool RotateFlag;
2. Fügen Sie den Optionsfeldern OnChange-Ereignisbehandlungsroutinen hinzu, indem Sie auf jedes Optionsfeld doppelklicken. Im Folgenden finden Sie den Delphi- und C++-Code für Cube1RadioButton. Der Code für Cube2RadioButton ist bis auf den Namen (Cube2 anstatt von Cube1) identisch.
  // The Delphi implementation for the radio button OnChange event
  procedure TForm1.Cube1RadioButtonChange(Sender: TObject); 
  begin
  //enables the group boxes to manipulate Cube1
    WidthGroupBox.Enabled := True;
    HeightGroupBox.Enabled := True;
    DepthGroupBox.Enabled := True;
    MoveGroupBox.Enabled := True;
    RotateGroupBox.Enabled := True;
  //updates the values for the track bars to display the current value of the Cube1.RotationAngle
    RotateFlag:=false;
    RotateXTrackBar.Value := Cube1.RotationAngle.X;
    RotateYTrackBar.Value := Cube1.RotationAngle.Y;
    RotateZTrackBar.Value := Cube1.RotationAngle.Z;
    RotateFlag:=True;
  //Saves the name of the 3D object to be manipulated
    ManipulatedItem:=Cube1.Name;
end;
  // The C++ implementation for the radio button OnChange event
 void __fastcall TForm3D1::Cube1RadioButtonChange(TObject *Sender)
{
  //enables the group boxes to manipulate Cube1
  WidthGroupBox->Enabled = true;
  HeightGroupBox->Enabled = true;
  DepthGroupBox->Enabled = true;

  MoveGroupBox->Enabled = true;
  RotateGroupBox->Enabled = true;
  //updates the values for the track bars to display the current value of the Cube1.RotationAngle
  RotateFlag = false;
  RotateXTrackBar->Value = Cube1->RotationAngle->X;
  RotateYTrackBar->Value = Cube1->RotationAngle->Y;
  RotateZTrackBar->Value = Cube1->RotationAngle->Z;
  RotateFlag = true;
  //Saves the name of the 3D object to be manipulated
  ManipulatedItem = Cube1->Name;
}

Bei LightRadioButton aktiviert der Code nicht alle Berabeitungsgruppenfelder. Das Verschieben und Ändern der Größe hat für TLight keine visuellen Effekte in der Szene. Die Implementierung von LightRadioButton lautet:

  // The Delphi implementation for the radio button OnChange event
  procedure TForm1.LightRadioButtonChange(Sender: TObject); 
  begin
  //disables the group boxes that move and resize the light
    WidthGroupBox.Enabled := False;
    HeightGroupBox.Enabled := False;
    DepthGroupBox.Enabled := False;
    MoveGroupBox.Enabled := False;
  // the light is manipulated only if it is on
    if(Light1.Enabled=True) then
    begin
      RotateGroupBox.Enabled := True;
      //updates the values for the track bars to display the current value of the Light1.RotationAngle
      RotateFlag:=false;
      RotateXTrackBar.Value := Light1.RotationAngle.X;
      RotateYTrackBar.Value := Light1.RotationAngle.Y;
      RotateZTrackBar.Value := Light1.RotationAngle.Z;
      RotateFlag:=True;
      //saves the name of the 3D object to be manipulated
      ManipulatedItem:=Cube1.Name;
   end
   else
      RotateGroupBox.Enabled := false;
   end;
end;
  // The C++ implementation for the radio button OnChange event
 void __fastcall TForm3D1::LightRadioButtonChange(TObject *Sender)
{
//disables the group boxes that move and resize the light
    WidthGroupBox->Enabled = false;
    HeightGroupBox->Enabled = false;
    DepthGroupBox->Enabled = false;
    MoveGroupBox->Enabled = false;
  // the light is manipulated only if it is on
    if (Light1->Enabled == true) 
    {
      RotateGroupBox->Enabled = true;
      //updates the values for the track bars to display the current value of the Light1.RotationAngle
      RotateFlag = false;
      RotateXTrackBar->Value = Light1->RotationAngle->X;
      RotateYTrackBar->Value = Light1->RotationAngle->Y;
      RotateZTrackBar->Value = Light1->RotationAngle->Z;
      RotateFlag = true;
      //saves the name of the 3D object to be manipulated
      ManipulatedItem=Cube1->Name;
   }
   else
      RotateGroupBox->Enabled = false;
}
3. Implementierung der LightOnOffButton-Schaltfläche:
  procedure TForm1.LightOnOffButtonClick(Sender: TObject);
  begin
    if Light1.Enabled = True then
    begin
      Light1.Enabled := False;
      LightOnOffButton.Text := 'ON';
      if(LightRadioButton.IsChecked) then
        RotateGroupBox.Enabled:=False;
    end
    else
    begin
      Light1.Enabled := True;
      LightOnOffButton.Text := 'OFF';
      if(LightRadioButton.IsChecked) then
      RotateGroupBox.Enabled:=True;
   end;
end;
void __fastcall TForm3D1::LightOnOffButtonClick(TObject *Sender)
{
  if (Light1->Enabled == true)
  {
    Light1->Enabled = false;
    LightOnOffButton->Text = "ON";
    if (LightRadioButton->IsChecked)
      RotateGroupBox->Enabled = false;
  }
  else
  {
    Light1->Enabled = true;
    LightOnOffButton->Text = "OFF";
    if (LightRadioButton->IsChecked) 
      RotateGroupBox->Enabled = true;
  }
}

Unterschiede zwischen "Licht an" und "Licht aus":

LightON.png LightOFF.png

4. Die Implementierungen für die Schaltflächen zur Größenänderung sind ähnlich. Im Folgenden finden Sie die Implementierung für das Vergrößern und Verkleinern der Breite des 3D-Objekts.
//Increasing and decreasing the Width of the 3D object
  procedure TForm1.IncreaseWidthButtonClick(Sender: TObject);
  begin
    TControl3D(FindComponent(ManipulatedItem)).Width:=TControl3D(FindComponent(ManipulatedItem)).Width+1;
  end;

  procedure TForm1.DecreaseWidthButtonClick(Sender: TObject);
  begin
    TControl3D(FindComponent(ManipulatedItem)).Width:=TControl3D(FindComponent(ManipulatedItem)).Width-1;
  end;
void __fastcall TForm3D1::IncreaseWidthButtonClick(TObject *Sender)
{
 ((TControl3D*)(FindComponent(ManipulatedItem)))->Width=((TControl3D*)(FindComponent(ManipulatedItem)))->Width+1;
}
void __fastcall TForm3D1::DecreaseWidthButtonClick(TObject *Sender)
{
 ((TControl3D*)(FindComponent(ManipulatedItem)))->Width=((TControl3D*)(FindComponent(ManipulatedItem)))->Width-1;
}
5. Die Implementierungen für die Schaltflächen zum Verschieben sind ähnlich. Im Folgenden finden Sie die Implementierung für das Verschieben des 3D-Objekts nach rechts und links.
  procedure TForm1.MoveRightButtonClick(Sender: TObject);
  begin
    TControl3D(FindComponent(ManipulatedItem)).Position.X:=TControl3D(FindComponent(ManipulatedItem)).Position.X+1;
  end;

  procedure TForm1.MoveLeftButtonClick(Sender: TObject);
  begin
    TControl3D(FindComponent(ManipulatedItem)).Position.X:=TControl3D(FindComponent(ManipulatedItem)).Position.X-1;
  end;
void __fastcall TForm3D1::MoveRightButtonClick(TObject *Sender)
{
 ((TControl3D*)(FindComponent(ManipulatedItem)))->Position->X=((TControl3D*)(FindComponent(ManipulatedItem)))->Position->X+1;
}
void __fastcall TForm3D1::MoveLeftButtonClick(TObject *Sender)
{
 ((TControl3D*)(FindComponent(ManipulatedItem)))->Position->X=((TControl3D*)(FindComponent(ManipulatedItem)))->Position->X-1;
}
  procedure TForm1.RotateXTrackBarChange(Sender: TObject);
  begin
    if (ManipulatedItem<>'') and (RotateFlag=True) then
     TControl3D(FindComponent(ManipulatedItem)).RotationAngle.X:= RotateXTrackBar.Value;
  end;
void __fastcall TForm3D1::RotateXTrackBarChange(TObject *Sender)
{
  if (ManipulatedItem!="" && RotateFlag==true) 
     ((TControl3D*)(FindComponent(ManipulatedItem)))->RotationAngle->X=RotateXTrackBar->Value;
}
7. Führen Sie das Projekt durch Drücken von F9 aus.
LightON.png
  • Markieren Sie Cube1Radiobutton. Wenn Sie auf die Schaltflächen Increase/Decrease klicken, wird die Größe des Würfels geändert.
    Cub1Risezed.png
  • Markieren Sie Cube1Radiobutton. Wenn Sie auf die Schaltflächen Left/Right klicken, ändert sich die Position des Würfels.
    Cub2Moved.png
  • Markieren Sie Cube1Radiobutton. Wenn Sie den Wert der Schieberegler erhöhen, wird der Würfel im Uhrzeigersinn gedreht, und wenn Sie den Wert verringern, wird der Würfel gegen den Uhrzeigersinn gedreht.
    Cub2Rotates.png
  • Markieren Sie LightRadiobutton. Wenn Sie den Wert der Schieberegler erhöhen, wird das Licht gedreht und der Effekt auf Cube2 sichtbar.
    LightRotates.png

Zurück

Siehe auch

Beispiele