Problem z pozycją tekstu 3d

0

Witam!!!

Problem Dotyczy Delphi XE2 i tworzenia aplikacji typu Firemonkey3D HD. Tworzę Okno Viewport3D a potem dodaję w nim TextLayer3D. Robię sobie animację rotację TextLayer3D za pomocą Timer-a(jeden Button Start/Stop). Postanowiłem, że gdy będę chciał zatrzymać animację, to napis powróci do wyjściowej pozycji(RotationAngle dla każdej osi równy zero). I tu pojawia się problem. Jeśli zrobię to dla jednej osi(np. X) to wszystko jest w porządku, ale gdy próbuję tak zrobić dla osi(X Y Z) to napis nie powraca do wyjściowej pozycji mimo iż TextLayer3D.RotationAngle(danej osi) jest równe zero.
Tu fragment kodu:
Użyłem suwaków, zmiana na suwakach co jeden.
Global - zmienna do włączania i wyłączania timera.

procedure TForm1.Button1Click(Sender: TObject);
begin
if Global=false then //gdy Global jest fałszem ustaw ją na true zmień nazwę przycisku ze Startu na Stop
begin // i uruchom Timer
Global:=true;
Button1.Text:='Stop';
Timer1.Enabled:=True;
end
else
begin
Global:=false;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Label1.Text:=FloatToStr(TrackBar1.Value);
Label5.Text:=FloatToStr(TrackBar2.Value);
Label6.Text:=FloatToStr(TrackBar3.Value);
Global:=False;
Timer1.Enabled:=False;
Button1.Text:='Start';
PozTrackZero:=False;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin

TextLayer3D1.RotationAngle.X:=TextLayer3D1.RotationAngle.X+TrackBar1.Value;
TextLayer3D1.RotationAngle.Y:=TextLayer3D1.RotationAngle.Y+TrackBar2.Value;
TextLayer3D1.RotationAngle.Z:=TextLayer3D1.RotationAngle.Z+TrackBar3.Value;
Label7.Text:='X: '+FloatToStr(TextLayer3D1.RotationAngle.X)+' Y:'+FloatToStr(TextLayer3D1.RotationAngle.Y)+' Z'+FloatToStr(TextLayer3D1.RotationAngle.Z);
 if Global=false then
    begin
    if TextLayer3D1.RotationAngle.X <> 0 then
       begin
       Trackbar1.Value:=1;
       end;
    if TextLayer3D1.RotationAngle.X = 0 then
          Trackbar1.Value:=0;
    if TextLayer3D1.RotationAngle.Y <> 0 then
       begin
       Trackbar2.Value:=1;
       end;
    if TextLayer3D1.RotationAngle.Y = 0 then
          Trackbar2.Value:=0;
    if TextLayer3D1.RotationAngle.Z <> 0 then
       begin
       Trackbar3.Value:=1;
       if TextLayer3D1.RotationAngle.Z = 0 then
          Trackbar3.Value:=0;
       end;
    if ((TextLayer3D1.RotationAngle.X = 0) and (TextLayer3D1.RotationAngle.Y = 0) and (TextLayer3D1.RotationAngle.Z = 0))then
        begin
        Timer1.Enabled:=False;
        Button1.Text:='Start';
        end;
    end;

// if TextLayer3D1.RotationAngle.X <> 0 then

end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
Label1.Text:=FloatToStr(TrackBar1.Value);

end;

procedure TForm1.TrackBar2Change(Sender: TObject);
begin
Label5.Text:=FloatToStr(TrackBar2.Value);
end;

procedure TForm1.TrackBar3Change(Sender: TObject);
begin
Label6.Text:=FloatToStr(TrackBar3.Value);
end;

end.

jak to zrobić?

0

Nie mam niestety żadnego doświadczenia jeśli chodzi o Delphi XE, więc wiele nie pomogę, jednak zastanawia mnie ta procedura:

procedure TForm1.Button1Click(Sender: TObject);
 begin
   if Global=false  then
     begin
     Global:=true;
     Button1.Text:='Stop';
     Timer1.Enabled:=True;
     end
   else
     begin
      Global:=false;
     end;
 end;

Dlaczego jeśli Global jest ustawiony na False to nie tylko zmieniasz jego wartość, ale ustawiasz treść przycisku i uruchamiasz tajmer, a jeśli Global jest na True to tylko zmieniasz jego wartość? Czy w tym drugim przypadku nie masz zatrzymać animacji i zmienić tekst przyciku? Jeśli tak, to warunek jest zbędny:

procedure TForm1.Button1Click(Sender: TObject);
const
  BUTTON_TEXT: array [Boolean] of String = ('Start', 'Stop');
begin
  Global := not Global;
  Button1.Text := BUTTON_TEXT[Global];
  Timer1.Enabled := Global;
end;

I powinno działać, choć nie wiem czy dobrze zrozumiałem;


Jeszcze jedno - używasz globalnej zmiennej (zapewne totalnie globalnej, a można jako publiczne pole klasy formularza) a nie wiem czy to ma sens, bo jeśli Timer1 jest na formularzu, na którym wykonujesz animację to ta zmienna jest zbędna, gdyż wystarczy zmieniać jedynie stan Timer1.Enabled; Nawet, jeśli chcesz w innych procedurach/funkcjach sprawdzać, czy tajmer jest uruchomiony to i tak będziesz to mógł wykonać bez dodatkowej zmiennej;


A jeszcze małe skrócenie kodu - tych warunków:

         begin
         if TextLayer3D1.RotationAngle.X <> 0 then
            begin
            Trackbar1.Value:=1;
            end;
         if TextLayer3D1.RotationAngle.X = 0 then
               Trackbar1.Value:=0;
         if TextLayer3D1.RotationAngle.Y <> 0 then
            begin
            Trackbar2.Value:=1;
            end;
         if TextLayer3D1.RotationAngle.Y = 0 then
               Trackbar2.Value:=0;
         if TextLayer3D1.RotationAngle.Z <> 0 then
            begin
            Trackbar3.Value:=1;
            if TextLayer3D1.RotationAngle.Z = 0 then
               Trackbar3.Value:=0;
            end;
         if ((TextLayer3D1.RotationAngle.X = 0) and (TextLayer3D1.RotationAngle.Y = 0) and (TextLayer3D1.RotationAngle.Z = 0))then
             begin
             Timer1.Enabled:=False;
             Button1.Text:='Start';
             end;
         end;

można się pozbyć na rzecz trzech linii:

Trackbar1.Value := Byte(TextLayer3D1.RotationAngle.X <> 0);
Trackbar2.Value := Byte(TextLayer3D1.RotationAngle.Y <> 0);
Trackbar3.Value := Byte(TextLayer3D1.RotationAngle.Z <> 0);

Prawda, że prościej? Aby przyspieszyć pisanie kodu skorzystaj z instrukcji wiążącej, by w kółko nie pisać TextLayer3D1.RotationAngle;

0

Ja tylko po raz milion pięćset sto dziewięćset przypomne, że wątki tagujemy nazwą środowiska/języka, a poza tym kod wstawiamy w odpowiednie znaczniki!!!

0

Przepraszam, ale gdy pisałem tego posta nie zauważyłem, która godzina na budziku u mnie, a do pracy trzeba iść i nie zdążyłem otagować tego tematu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1