Можно ли выводить 2 OpenGL сцены, одновременно, в разных
От: Аноним  
Дата: 23.11.05 11:51
Оценка:
Привет, All!

юзаю OpenGL под Delphi
можно ли в приложении c OpenGL выводить изображение в несколько форм?
у меня написан класс базовой формы, если вызвать одного наследника все работат хорошо, если одновременно с первым вызвать второго, работа нарушается, прекращается правильная перерисовка формы, почему и как этого можно избежать?
возможно бага в настройках?

unit uGLForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, OpenGL,
  Db, ADODB, ExtCtrls;

type
  TPoint3d = record
    iIdStar : integer;
    x,y,z : GLdouble;
    MaterialColor: Array [0..3] of GLfloat;
    Name : string;
  end;

    TGLForm = class(TForm)
    Timer: TTimer;
    tMain: TADOTable;
    procedure FormPaint(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure TimerTimer(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    DC : HDC;
    hrc : HGLRC;
    AngleX, AngleY : GLfloat;
    Perspective : GLFloat;

    base : GLuint;
    myfont : HFONT;
    test : HGDIOBJ;
    
    procedure SetDCPixelFormat;
    procedure InitializeRC;
    procedure Camera;
  protected
    procedure CalcSelectLine(mouse_x, mouse_y:integer; var p1, p2 : TPoint3D);
    procedure DrawScene; virtual;
    procedure Draw; virtual;
    procedure DrawText(sMessage : string; x,y,z : GLfloat);
    procedure InitText;
  public
    arPoint : array of TPoint3D;
    stParams : TStrings;
    procedure InitForm;
  end;


implementation

{$R *.DFM}

{ TForm1 }

procedure TGLForm.Camera;
begin
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(Perspective, ClientWidth / ClientHeight, 1.0, 20.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
  gluLookAt(0.0, 30.0, 10.0, 0, 0, -5.0, 0, 1, 0);
end;

procedure TGLForm.DrawScene;
begin
  // очистка буфера цвета и буфера глубины
  glClearColor (0.0, 0.0, 0.0, 0.0); // цвет фона
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  Camera;
  // трехмерность
  glLoadIdentity;
  glTranslatef( 0, 0, -3.0);
  glRotatef(30.0, 1.0, 0.0, 0.0);
  glRotatef(AngleX, 0.0, 1.0, 0.0); // поворот на угол
  glRotatef(AngleY, 0.1, 0.0, 0.0); // поворот на угол
  Draw;
  SwapBuffers(DC);   // конец работы
end;

procedure TGLForm.InitializeRC;
begin
  glEnable(GL_DEPTH_TEST); // разрешаем тест глубины
  glEnable(GL_LIGHTING);   // разрешаем работу с освещенностью
  glEnable(GL_LIGHT0);     // включаем источник света 0
  glEnable(GL_COLOR_MATERIAL);
end;

procedure TGLForm.SetDCPixelFormat;
var
  nPixelFormat: Integer;
  pfd: TPixelFormatDescriptor;
begin
  FillChar(pfd, SizeOf(pfd), 0);
  with pfd do begin
    nSize     := sizeof(pfd);
    nVersion  := 1;
    dwFlags   := PFD_DRAW_TO_WINDOW or
                 PFD_SUPPORT_OPENGL or
                 PFD_DOUBLEBUFFER;
    iPixelType:= PFD_TYPE_RGBA;
    cColorBits:= 24;
    cDepthBits:= 32;
    iLayerType:= PFD_MAIN_PLANE;
  end;
  nPixelFormat := ChoosePixelFormat(DC, @pfd);
  SetPixelFormat(DC, nPixelFormat, @pfd);
end;

procedure TGLForm.FormPaint(Sender: TObject);
var
  ps : TPaintStruct;
begin
  BeginPaint(Handle, ps);
  DrawScene;
  EndPaint(Handle, ps);
end;

procedure TGLForm.DrawText(sMessage: string; x, y, z: GLfloat);
var
  A: array[0..255] of Char;
begin
  StrPCopy(A, sMessage);
  glRasterPos3f(x,y,z);
  glPushAttrib(GL_LIST_BIT);
  glListBase(base - 32);
  glCallLists(length(sMessage), GL_UNSIGNED_BYTE, @A);
  glPopAttrib();
end;

procedure TGLForm.InitText;
begin
  base := glGenLists(96);
  DC := wglGetCurrentDC();

  if(base = GL_INVALID_VALUE) and  (base = GL_INVALID_OPERATION)then exit;
  myfont := CreateFont(-9,
            0,0,0,
            FW_REGULAR,
            0,0,0,
            ANSI_CHARSET,
            OUT_TT_PRECIS,
            CLIP_DEFAULT_PRECIS,
            ANTIALIASED_QUALITY,
            FF_DONTCARE or DEFAULT_PITCH,
            'Agency FB'); //шрифт

  if myfont = 0 then exit;
  test := SelectObject(DC, myfont);
  wglUseFontBitmaps(DC, 32, 96, base);

  SelectObject(DC, test);
  DeleteObject(myfont);
end;

procedure TGLForm.CalcSelectLine(mouse_x, mouse_y: integer; var p1,
  p2: TPoint3D);
var
  viewport : array [0..3] of GLint;    // параметры viewport-a.
  projection : array [0..15] of GLdouble; // матрица проекции.
  modelview : array [0..15] of GLdouble;  // видовая матрица.
  vx,vy,vz : GLdouble;       // координаты курсора мыши в системе координат viewport-a.
  wx,wy,wz : GLdouble;       // возвращаемые мировые координаты.
begin
  // mouse_x, mouse_y  - оконные координаты курсора мыши.
  // p1, p2            - возвращаемые параметры - концы селектирующего отрезка,
  //                     лежащие соответственно на ближней и дальней плоскостях
  //                     отсечения.

  glGetIntegerv(GL_VIEWPORT,@viewport);           // узнаём параметры viewport-a.
  glGetDoublev(GL_PROJECTION_MATRIX,@projection); // узнаём матрицу проекции.
  glGetDoublev(GL_MODELVIEW_MATRIX,@modelview);   // узнаём видовую матрицу.
  // переводим оконные координаты курсора в систему координат viewport-a.
  vx := mouse_x;
  vy := height - mouse_y - 1; // где height - текущая высота окна.

  // вычисляем ближний конец селектирующего отрезка.
  vz := -1;
  gluUnProject(vx, vy, vz, @modelview, @projection, @viewport, wx, wy, wz);
  p1.x := wx;
  p1.y := wy;
  p1.z := wz;
  // вычисляем дальний конец селектирующего отрезка.
  vz := 1;
  gluUnProject(vx, vy, vz, @modelview, @projection, @viewport, wx, wy, wz);
  p2.x := wx;
  p2.y := wy;
  p2.z := wz;
end;

procedure TGLForm.FormDestroy(Sender: TObject);
begin
  stParams.Free;
end;

procedure TGLForm.TimerTimer(Sender: TObject);
begin
  AngleX := AngleX + 0.05;
  If (AngleX >= 360.0) then AngleX := 0.0;
  If (AngleY >= 360.0) then AngleY := 0.0;
  InvalidateRect(Handle, nil, False); // перерисовка региона (Windows API)
end;

procedure TGLForm.FormResize(Sender: TObject);
begin
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(30.0, Width / Height, 1.0, 10.0);
  glViewport(0, 0, Width, Height);
  glMatrixMode(GL_MODELVIEW);
end;

procedure TGLForm.Draw;
begin
end;

procedure TGLForm.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
  if WheelDelta < 0 then
      Perspective := Perspective - 0.5
  else
      Perspective := Perspective + 0.5;
end;

procedure TGLForm.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_LEFT :   AngleX := AngleX - 0.5;
    VK_RIGHT:   AngleX := AngleX + 0.5;
    VK_UP   :   AngleY := AngleY - 0.5;
    VK_DOWN :   AngleY := AngleY + 0.5;
  end;
end;

procedure TGLForm.InitForm;
begin
  stParams := TStrings.Create;
  Perspective := 40.0;

  AngleX := 0.0;
  AngleY := 0.0;

  DC := GetDC(Handle);
  SetDCPixelFormat;
  hrc := wglCreateContext(DC);

  wglMakeCurrent(DC, hrc);
  InitializeRC;
  InitText;
end;

end.



вызов в наследниках:



 ...
procedure TfmMap.FormCreate(Sender: TObject);
begin
  inherited;
  InitForm;
  tMain.Open;
  SetLength(arPoint, tMain.RecordCount);
  InitMap;
  Timer.Enabled := True;
end;
...


Спасибо.
Re: Можно ли выводить 2 OpenGL сцены, одновременно, в разных
От: FunnyRabbit Россия  
Дата: 23.11.05 13:42
Оценка:
А>
А>unit uGLForm;

А>interface

А>uses
А>  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, OpenGL,
А>  Db, ADODB, ExtCtrls;

А>type
А>  TPoint3d = record
А>    iIdStar : integer;
А>    x,y,z : GLdouble;
А>    MaterialColor: Array [0..3] of GLfloat;
А>    Name : string;
А>  end;

А>    TGLForm = class(TForm)
А>    Timer: TTimer;
А>    tMain: TADOTable;
А>    procedure FormPaint(Sender: TObject);
А>    procedure FormDestroy(Sender: TObject);
А>    procedure TimerTimer(Sender: TObject);
А>    procedure FormResize(Sender: TObject);
А>    procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
А>      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
А>    procedure FormKeyDown(Sender: TObject; var Key: Word;
А>      Shift: TShiftState);
А>  private
А>    DC : HDC;
А>    hrc : HGLRC;
А>    AngleX, AngleY : GLfloat;
А>    Perspective : GLFloat;

А>    base : GLuint;
А>    myfont : HFONT;
А>    test : HGDIOBJ;
    
А>    procedure SetDCPixelFormat;
А>    procedure InitializeRC;
А>    procedure Camera;
А>  protected
А>    procedure CalcSelectLine(mouse_x, mouse_y:integer; var p1, p2 : TPoint3D);
А>    procedure DrawScene; virtual;
А>    procedure Draw; virtual;
А>    procedure DrawText(sMessage : string; x,y,z : GLfloat);
А>    procedure InitText;
А>  public
А>    arPoint : array of TPoint3D;
А>    stParams : TStrings;
А>    procedure InitForm;
А>  end;


А>implementation

А>{$R *.DFM}

А>{ TForm1 }

А>procedure TGLForm.Camera;
А>begin
А>  glMatrixMode(GL_PROJECTION);
А>  glLoadIdentity;
А>  gluPerspective(Perspective, ClientWidth / ClientHeight, 1.0, 20.0);
А>  glMatrixMode(GL_MODELVIEW);
А>  glLoadIdentity;
А>  gluLookAt(0.0, 30.0, 10.0, 0, 0, -5.0, 0, 1, 0);
А>end;

А>procedure TGLForm.DrawScene;
А>begin
А>  // очистка буфера цвета и буфера глубины
А>  glClearColor (0.0, 0.0, 0.0, 0.0); // цвет фона
А>  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
А>  Camera;
А>  // трехмерность
А>  glLoadIdentity;
А>  glTranslatef( 0, 0, -3.0);
А>  glRotatef(30.0, 1.0, 0.0, 0.0);
А>  glRotatef(AngleX, 0.0, 1.0, 0.0); // поворот на угол
А>  glRotatef(AngleY, 0.1, 0.0, 0.0); // поворот на угол
А>  Draw;
А>  SwapBuffers(DC);   // конец работы
А>end;

А>procedure TGLForm.InitializeRC;
А>begin
А>  glEnable(GL_DEPTH_TEST); // разрешаем тест глубины
А>  glEnable(GL_LIGHTING);   // разрешаем работу с освещенностью
А>  glEnable(GL_LIGHT0);     // включаем источник света 0
А>  glEnable(GL_COLOR_MATERIAL);
А>end;

А>procedure TGLForm.SetDCPixelFormat;
А>var
А>  nPixelFormat: Integer;
А>  pfd: TPixelFormatDescriptor;
А>begin
А>  FillChar(pfd, SizeOf(pfd), 0);
А>  with pfd do begin
А>    nSize     := sizeof(pfd);
А>    nVersion  := 1;
А>    dwFlags   := PFD_DRAW_TO_WINDOW or
А>                 PFD_SUPPORT_OPENGL or
А>                 PFD_DOUBLEBUFFER;
А>    iPixelType:= PFD_TYPE_RGBA;
А>    cColorBits:= 24;
А>    cDepthBits:= 32;
А>    iLayerType:= PFD_MAIN_PLANE;
А>  end;
А>  nPixelFormat := ChoosePixelFormat(DC, @pfd);
А>  SetPixelFormat(DC, nPixelFormat, @pfd);
А>end;

А>procedure TGLForm.FormPaint(Sender: TObject);
А>var
А>  ps : TPaintStruct;
А>begin
А>  BeginPaint(Handle, ps);
А>  DrawScene;
А>  EndPaint(Handle, ps);
А>end;

А>procedure TGLForm.DrawText(sMessage: string; x, y, z: GLfloat);
А>var
А>  A: array[0..255] of Char;
А>begin
А>  StrPCopy(A, sMessage);
А>  glRasterPos3f(x,y,z);
А>  glPushAttrib(GL_LIST_BIT);
А>  glListBase(base - 32);
А>  glCallLists(length(sMessage), GL_UNSIGNED_BYTE, @A);
А>  glPopAttrib();
А>end;

А>procedure TGLForm.InitText;
А>begin
А>  base := glGenLists(96);
А>  DC := wglGetCurrentDC();

А>  if(base = GL_INVALID_VALUE) and  (base = GL_INVALID_OPERATION)then exit;
А>  myfont := CreateFont(-9,
А>            0,0,0,
А>            FW_REGULAR,
А>            0,0,0,
А>            ANSI_CHARSET,
А>            OUT_TT_PRECIS,
А>            CLIP_DEFAULT_PRECIS,
А>            ANTIALIASED_QUALITY,
А>            FF_DONTCARE or DEFAULT_PITCH,
А>            'Agency FB'); //шрифт

А>  if myfont = 0 then exit;
А>  test := SelectObject(DC, myfont);
А>  wglUseFontBitmaps(DC, 32, 96, base);

А>  SelectObject(DC, test);
А>  DeleteObject(myfont);
А>end;

А>procedure TGLForm.CalcSelectLine(mouse_x, mouse_y: integer; var p1,
А>  p2: TPoint3D);
А>var
А>  viewport : array [0..3] of GLint;    // параметры viewport-a.
А>  projection : array [0..15] of GLdouble; // матрица проекции.
А>  modelview : array [0..15] of GLdouble;  // видовая матрица.
А>  vx,vy,vz : GLdouble;       // координаты курсора мыши в системе координат viewport-a.
А>  wx,wy,wz : GLdouble;       // возвращаемые мировые координаты.
А>begin
А>  // mouse_x, mouse_y  - оконные координаты курсора мыши.
А>  // p1, p2            - возвращаемые параметры - концы селектирующего отрезка,
А>  //                     лежащие соответственно на ближней и дальней плоскостях
А>  //                     отсечения.

А>  glGetIntegerv(GL_VIEWPORT,@viewport);           // узнаём параметры viewport-a.
А>  glGetDoublev(GL_PROJECTION_MATRIX,@projection); // узнаём матрицу проекции.
А>  glGetDoublev(GL_MODELVIEW_MATRIX,@modelview);   // узнаём видовую матрицу.
А>  // переводим оконные координаты курсора в систему координат viewport-a.
А>  vx := mouse_x;
А>  vy := height - mouse_y - 1; // где height - текущая высота окна.

А>  // вычисляем ближний конец селектирующего отрезка.
А>  vz := -1;
А>  gluUnProject(vx, vy, vz, @modelview, @projection, @viewport, wx, wy, wz);
А>  p1.x := wx;
А>  p1.y := wy;
А>  p1.z := wz;
А>  // вычисляем дальний конец селектирующего отрезка.
А>  vz := 1;
А>  gluUnProject(vx, vy, vz, @modelview, @projection, @viewport, wx, wy, wz);
А>  p2.x := wx;
А>  p2.y := wy;
А>  p2.z := wz;
А>end;

А>procedure TGLForm.FormDestroy(Sender: TObject);
А>begin
А>  stParams.Free;
А>end;

А>procedure TGLForm.TimerTimer(Sender: TObject);
А>begin
А>  AngleX := AngleX + 0.05;
А>  If (AngleX >= 360.0) then AngleX := 0.0;
А>  If (AngleY >= 360.0) then AngleY := 0.0;
А>  InvalidateRect(Handle, nil, False); // перерисовка региона (Windows API)
А>end;

А>procedure TGLForm.FormResize(Sender: TObject);
А>begin
А>  glMatrixMode(GL_PROJECTION);
А>  glLoadIdentity;
А>  gluPerspective(30.0, Width / Height, 1.0, 10.0);
А>  glViewport(0, 0, Width, Height);
А>  glMatrixMode(GL_MODELVIEW);
А>end;

А>procedure TGLForm.Draw;
А>begin
А>end;

А>procedure TGLForm.FormMouseWheel(Sender: TObject; Shift: TShiftState;
А>  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
А>begin
А>  if WheelDelta < 0 then
А>      Perspective := Perspective - 0.5
А>  else
А>      Perspective := Perspective + 0.5;
А>end;

А>procedure TGLForm.FormKeyDown(Sender: TObject; var Key: Word;
А>  Shift: TShiftState);
А>begin
А>  case Key of
А>    VK_LEFT :   AngleX := AngleX - 0.5;
А>    VK_RIGHT:   AngleX := AngleX + 0.5;
А>    VK_UP   :   AngleY := AngleY - 0.5;
А>    VK_DOWN :   AngleY := AngleY + 0.5;
А>  end;
А>end;

А>procedure TGLForm.InitForm;
А>begin
А>  stParams := TStrings.Create;
А>  Perspective := 40.0;

А>  AngleX := 0.0;
А>  AngleY := 0.0;

А>  DC := GetDC(Handle);
А>  SetDCPixelFormat;
А>  hrc := wglCreateContext(DC);

А>  wglMakeCurrent(DC, hrc);
А>  InitializeRC;
А>  InitText;
А>end;

А>end.
А>



А>вызов в наследниках:




А>
А> ...
А>procedure TfmMap.FormCreate(Sender: TObject);
А>begin
А>  inherited;
А>  InitForm;
А>  tMain.Open;
А>  SetLength(arPoint, tMain.RecordCount);
А>  InitMap;
А>  Timer.Enabled := True;
А>end;
А>...
А>


А>Спасибо.


Нет никакой баги. Незнаю как в делфи, но вообще ты рисуешь на DC — device context. Это твое так сказать окно для рисования. Если в делфи реализация методов OpenGL из
То что меня не убивает, делает меня умнее.
Re: Можно ли выводить 2 OpenGL сцены, одновременно, в разных
От: FunnyRabbit Россия  
Дата: 23.11.05 13:45
Оценка:
Извини. Не законцил. Нельзя т.к.



procedure TGLForm.DrawScene;
begin
  // очистка буфера цвета и буфера глубины
  glClearColor (0.0, 0.0, 0.0, 0.0); // цвет фона
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  Camera;
  // трехмерность
  glLoadIdentity;
  glTranslatef( 0, 0, -3.0);
  glRotatef(30.0, 1.0, 0.0, 0.0);
  glRotatef(AngleX, 0.0, 1.0, 0.0); // поворот на угол
  glRotatef(AngleY, 0.1, 0.0, 0.0); // поворот на угол
  Draw;
  SwapBuffers(DC); << -- Это твой девайс - контекст. 
end;

Можешь попробовать переключать контекст устройства, но одновременно.... Увы.
То что меня не убивает, делает меня умнее.
Re[2]: Можно ли выводить 2 OpenGL сцены, одновременно, в раз
От: Аноним  
Дата: 23.11.05 14:16
Оценка:
Здравствуйте, FunnyRabbit, Вы писали:

FR>Извини. Не законцил. Нельзя т.к.


FR>


FR>procedure TGLForm.DrawScene;
FR>begin
FR>  // очистка буфера цвета и буфера глубины
FR>  glClearColor (0.0, 0.0, 0.0, 0.0); // цвет фона
FR>  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
FR>  Camera;
FR>  // трехмерность
FR>  glLoadIdentity;
FR>  glTranslatef( 0, 0, -3.0);
FR>  glRotatef(30.0, 1.0, 0.0, 0.0);
FR>  glRotatef(AngleX, 0.0, 1.0, 0.0); // поворот на угол
FR>  glRotatef(AngleY, 0.1, 0.0, 0.0); // поворот на угол
FR>  Draw;
FR>  SwapBuffers(DC); << -- Это твой девайс - контекст. 
FR>end;
FR>

FR>Можешь попробовать переключать контекст устройства, но одновременно.... Увы.

а можно здесь немного поподробней, здесь API'шные функции используются, я их не очень часто юзаю
как можно реализовать переключение контекста устройства (пожалуйста без библиотек типа MFC)

можно и не одновременно, устроит вариант когда вторая форма вызывается как модальная, и после работы с ней мы возвращаемся к работе с первой, но как сначала сохранить а потом восстановить рабочие настройки
Re[3]: Можно ли выводить 2 OpenGL сцены, одновременно, в раз
От: FunnyRabbit Россия  
Дата: 23.11.05 14:44
Оценка:
procedure TGLForm.InitForm;
begin
  stParams := TStrings.Create;
  Perspective := 40.0;

  AngleX := 0.0;
  AngleY := 0.0;

  DC := GetDC(Handle); <<-- вот тут ты его включаешь
  SetDCPixelFormat;
  hrc := wglCreateContext(DC);

  wglMakeCurrent(DC, hrc);
  InitializeRC;
  InitText;
end;

А вот как можно сделать:


procedure TGLForm.InitDC(Handle: HWND) //Прошлый твой InitForm;
begin
  stParams := TStrings.Create;
  Perspective := 40.0;

  AngleX := 0.0;
  AngleY := 0.0;

  DC := GetDC(Handle);
  SetDCPixelFormat;
  hrc := wglCreateContext(DC);

  wglMakeCurrent(DC, hrc);
  InitializeRC;
  InitText;
end;


и как там у тебя


// вызов в наследниках:
 ...
procedure TfmMap.FormCreate(Sender: TObject);
begin
  inherited;
  InitDC(Self.Handle) //  InitForm;
  tMain.Open;
  SetLength(arPoint, tMain.RecordCount);
  InitMap;
  Timer.Enabled := True;
end;
...


где InitDC(Self.Handle) Дескриптор твой формы.
Я бы на твоем месте реализовал (а точнее так и делал раньше) класс в который можно передать HWND любого окна и т.п.
Типа

type 
  TOpenGLRender = class
   .......
   hDC: HDC;
   hWnd: HWND;
   fGLRC: HGLRC;
   public 
   .....
    procedure InitDC(hwnd: HWND);
   ....
end;

А потом:

procedure ....();
var
  oglr: TOpenGLRender;
begin
  oglr := TOpenGLRender.Create;
  oglr.InitDC(Self.Handle);
end;


Не знаю. Может если вставить вместо hwnd 0, то получиться рендерить на рабочем столе?

Have fun!
То что меня не убивает, делает меня умнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.