Création d'une interface 2D dans une application 3D (tutoriel FireMonkey 3D)
Remonter à Tutoriel : Création d'une application 3D FireMonkey
Une application 3D ne peut pas utiliser directement les composants 2D tels que les boutons ou les listes. Si un composant 2D est glissé et déposé sur un conteneur 3D, le composant ne sera pas restitué mais il apparaîtra dans la vue Structure sous la forme d'un contrôle enfant. Toutefois, un moyen simple de traiter ce problème consiste à créer un pont entre les scènes 3D et 2D. FireMonkey fournit le composant FMX.Layers3D.TLayer3D à cet effet.
Sommaire
Ajout et ajustement d'une surface 2D (TLayer3D) et d'un TButton
- Avec la fiche du tutoriel précédent sélectionnée dans l'inspecteur d'objets ou la vue Structure, double-cliquez sur TLayer3D dans la Palette d'outils.
- Vous pouvez maintenant utiliser le composant TLayer3D en tant que surface pour les composants FireMonkey 2D.
- Avec TLayer3D sélectionné dans la vue Structure ou l'inspecteur d'objets, ajoutez un TButton. Dans la vue Structure, assurez-vous que le bouton est l'enfant de la couche, et pas un enfant de la fiche (si vous avez besoin de corriger la hiérarchie, faites glisser le TButton et déposez-le sur la couche).
- Pour simuler une surface 2D, changez le type Projection du composant TLayer3D. Dans l'inspecteur d'objets, définissez la propriété suivante de la couche
- Projection = Screen
- Une projection d'écran est une projection pixel-à-pixel du plan d'écran avec une caméra fixe (invisible), et l'avant-plan du champ de vue 3d est maintenant un plan d'écran. Chaque objet est toujours 3D, mais il peut être manipulé comme s'il était 2D.
- Votre application 3D devrait maintenant ressembler à la figure suivante :
- Comme vous le voyez, le composant TLayer3D a éclipsé la scène, en n'en laissant apparaître qu'une partie. Dans l'inspecteur d'objets, avec TLayer3D détenant la focalisation, définissez les propriétés suivantes
- Align sur
MostRight
(ou tout autre alignement de votre choix) - Width sur
150
(ou toute autre largeur de votre choix, spécifiée en pixels)
- Align sur
Ajout et arrangement des composants 2D
Supprimez maintenant le bouton ajouté, pour ajouter d'autres composants à travers lesquels les objets 3D de la fiche sont pivotés, déplacés ou redimensionnés.
- Avec TLayer3D détenant la focalisation, ajoutez cinq TGroupBox.
- Sélectionnez toutes les zones de groupe dans la vue Structure en appuyant sur CTRL et en cliquant avec la souris, et dans l'inspecteur d'objets, définissez Align sur
Top
. - Sélectionnez les trois premières zones de groupe dans la partie supérieure, et dans l'inspecteur d'objets, définissez Height sur
70
(ou sur une autre valeur qui vous semble mieux convenir à la disposition finale). - Sélectionnez chaque TGroupBox et définissez
- Ajoutez des paires de boutons aux trois premiers TGroupBox. Un bouton est utilisé pour augmenter la largeur, la hauteur et la profondeur, et un autre bouton pour les diminuer.
- Changez les noms des paires de boutons comme suit :
- IncreaseWidthButton et DecreaseWidthButton
- IncreaseHeightButton et DecreaseHeightButton
- IncreaseDepthButton et DecreaseDepthButton
- Changez Text en concordance avec le nom du bouton.
- Ajoutez trois jeux de paires de boutons dans les zones de groupe Move.
- Changez les noms des paires de boutons comme suit :
- MoveRightButton et MoveLeftButton
- MoveDownButton et MoveUpButton
- MoveBackButton et MoveFrontButton
- Changez Text en concordance avec le nom du bouton.
- Ajoutez trois composants TTrackBar, utilisés pour pivoter l'objet 3D sur chaque axe, à la zone de groupe Rotate.
- Définissez les noms des TTrackBar sur RotateXTrackBar, RotateYTrackBar et RotateZTrackBar.
- Dans l'inspecteur d'objets définissez, pour chaque barre de suivi, la propriété Min sur
-360
, et la propriété Max sur360
.
- Sélectionnez toutes les zones de groupe dans la vue Structure en appuyant sur CTRL et en cliquant avec la souris, et dans l'inspecteur d'objets, définissez Align sur
- Ajoutez un autre TLayer3D à la fiche.
- Avec le nouveau TLayer3D détenant la focalisation, dans l'inspecteur d'objets, définissez la propriété Projection sur
Screen
, et la propriété Align surTop
. - Ajoutez deux composants TGroupBox au nouveau TLayer3D.
- Sélectionnez chaque TGroupBox et définissez
- Ajoutez trois TRadioButton au ManipulateItemGroupBox, un pour chaque objet 3D dans la scène.
- Sélectionnez chaque TRadioButton et définissez
- Ajoutez un TButton au LightGroupBox.
- Sélectionnez le bouton et définissez
- Avec le nouveau TLayer3D détenant la focalisation, dans l'inspecteur d'objets, définissez la propriété Projection sur
La disposition finale doit ressembler à ceci :
Ajout d'événements et de gestionnaires d'événements
Vous disposez maintenant d'une simple scène 3D dans laquelle vous pouvez facilement assigner des événements aux objets.
- 1. Pour obtenir l'objet 3D qui doit être manipulé, déclarez une variable chaîne globale afin de conserver le nom de l'objet.
La barre de suivi offre la possibilité de pivoter l'objet détenant la focalisation sur l'événement OnChange. Pour éviter la mise à jour des angles de rotation pour l'objet précédent quand un autre objet est sélectionné, ajoutez une variable booléenne RotateFlag. Si elle est définie sur False, le code du gestionnaire d'événements OnChange ne se déclenchera pas.
//Delphi declaration
var
Form1: TForm1;
ManipulatedItem: String;
RotateFlag: boolean;
// C++ declaration
TForm3D1 *Form3D1;
System::UnicodeString ManipulatedItem;
bool RotateFlag;
- 2. Ajoutez des gestionnaires d'événements OnChange aux boutons radio en double-cliquant sur chacun d'eux. Voici ci-dessous le code Delphi et C++ pour Cube1RadioButton. Le code pour Cube2RadioButton est le même, sauf que Cube2 est utilisé au lieu de Cube1.
// 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;
}
Pour LightRadioButton, le code n'active pas toutes les zones de groupe de manipulation. Le déplacement et le redimensionnement du TLight a maintenant des effets visuels sur la scène. L'implémentation pour LightRadioButton est
// 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. Implémentation du bouton LightOnOffButton :
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;
}
}
Différence entre "Light on" et "Light off"
- 4. Le redimensionnement des boutons a une implémentation similaire. Voici ci-dessous l'implémentation de l'augmentation et de la diminution de la largeur de l'objet 3D.
//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. Le déplacement des boutons a une implémentation similaire. Voici ci-dessous l'implémentation du déplacement de l'objet 3D vers la droite et la gauche.
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;
}
- 6. La rotation des barres de suivi a une implémentation similaire. Voici ci-dessous l'implémentation de la rotation de l'objet 3D autour de l'axe X.
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. Exécutez le projet en appuyant sur F9.
-
- Vérifiez Cube1Radiobutton. Quand vous cliquez sur les boutons Increase/Decrease, la taille du cube change.
- Vérifiez Cube1Radiobutton. Quand vous cliquez sur les boutons Left / Right, la position du cube change.
- Vérifiez Cube1Radiobutton. Quand vous augmentez la valeur des barres de suivi, le cube subit une rotation dans le sens des aiguilles d'une montre. Si la valeur est diminuée, le cube subit une rotation dans le sens contraire des aiguilles d'une montre.
- Vérifiez LightRadiobutton. Quand vous augmentez la valeur des barres de suivi, la lumière subit une rotation et son effet peut être vu sur Cube2.
Précédent
Voir aussi
- Création d'un composant FireMonkey (Delphi)
- Création d'un composant FireMonkey (C++)
- Application 3D multi-périphérique
- Utilisation des événements et des gestionnaires d'événement
Exemples
- Exemple FireMonkey 3D Arrows
- Exemple FireMonkey First App3D
- Exemple FireMonkey GUI3d
- Exemple FireMonkey Cameras Textures 3D