- Код: Выделить всё
- {$mode objfpc}{$h+}
 unit tr_application;
 interface
 
 uses
 {$ifdef windows}
 tr_windows,
 {$endif}
 classes, tr_logger;
 type
 TApplication = class
 private
 fwindow_name : string;
 fwindow_width : integer;
 fwindow_height : integer;
 ffullscreen : boolean;
 fparams : tstringList;
 
 flog : tlogger; static;
 public
 
 property window_width : integer read fwindow_width write fwindow_width;
 property window_height : integer read fwindow_height write fwindow_height;
 property window_name : string read fwindow_name write fwindow_name;
 
 constructor create();
 destructor destroy();
 class function get_instance() : tapplication;
 function create_window(app_name : pchar; awindow_width, awindow_height : longint; afullscreen : boolean ) : boolean;
 procedure parse_params(aparams : string);
 procedure main_loop();
 private
 
 end;
 
 implementation
 
 var
 app : TApplication = nil;
 
 constructor TApplication.create();
 begin
 fwindow_name := 'tr_application_empty';
 fwindow_width := 800;
 fwindow_height := 600;
 ffullscreen := false;
 flog := tlogger.create('TEST_LOG.TXT');
 end;
 
 destructor TApplication.destroy();
 begin
 kill_gl_window();
 end;
 
 class function TApplication.get_instance() : tapplication;
 begin
 if(app = nil) then
 app := tapplication.create();
 
 result := app;
 flog.write('Application has been created...');
 end;
 
 
 function TApplication.create_window(app_name : pchar; awindow_width, awindow_height : longint; afullscreen : boolean ) : boolean;
 begin
 if app_name <> '' then
 fwindow_name := app_name;
 
 fwindow_width := awindow_width;
 fwindow_height := awindow_height;
 ffullscreen := afullscreen;
 // следующая функция создаёт само окно с opengl контекстом, но в нём же и обработка всех событий, как бы их вытащить?
 result := create_gl_window(pchar(fwindow_name), fwindow_width, fwindow_height, ffullscreen);
 end;
 
 
 procedure TApplication.main_loop();
 begin
 process_messages();
 end;
 
 
 procedure TApplication.parse_params(aparams : string);
 begin
 
 end;
 
 end.
Модуль создания окна, для Windows, под Linux планировался такой же модуль, с такими же функциями:
function create_gl_window(app_name : pchar; wnd_width, wnd_height : longint; app_fullscreen : boolean) : boolean;
procedure kill_gl_window();
procedure process_messages();
только другой реализацией.
- Код: Выделить всё
- {$mode objfpc}{$h+}
 {$apptype gui}
 unit tr_windows;
 interface
 uses
 gl, glu, windows;
 
 var
 msg : tmsg; // Windows messages
 hwindow : hwnd; // Windows Handle to the OGL Window
 dc_window : hdc; // Device Context for the OGL Window
 rc_window : hglrc; // Render Context for the OGL Window
 
 width, height : longint;
 fullscreen, active : boolean;
 
 function create_gl_window(app_name : pchar; wnd_width, wnd_height : longint; app_fullscreen : boolean) : boolean;
 procedure kill_gl_window();
 procedure process_messages();
 implementation
 
 procedure gl_init();
 begin
 glShadeModel(GL_SMOOTH);
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 glClearColor( 0.0, 0.0, 0.0, 1.0 );
 glTranslatef(0.0, 0.0, -1.0);
 end;
 
 procedure gl_resize(awidth : integer; aheight : integer);
 var
 ar : real;
 begin
 if (aheight = 0) then
 aheight := 1;
 
 width := awidth;
 height := aheight;
 
 glViewport(0, 0, awidth, aheight);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 
 ar := awidth/aheight;
 glOrtho(0, 10000, 0, 10000, 0.0, 0.0);
 
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity;
 end;
 
 procedure gl_render();
 var
 i, x, y, segments_amount : integer;
 angle, r, dx, dy : real;
 begin
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 
 { draw here }
 { тут просто рисование, рисуем бублик и две полоски }
 glClear( GL_COLOR_BUFFER_BIT );
 glLoadIdentity();
 
 glColor3f(0.0, 0.0, 1.0);
 glBegin(GL_LINES);
 glVertex2f(0.0, 0.0);
 glVertex2f(0.0, 1.0);
 glEnd();
 
 glColor3f(1.0, 0.0, 0.0);
 glBegin(GL_LINES);
 glVertex2f(0.0, 0.0);
 glVertex2f(1.0, 0.0);
 glEnd();
 
 glColor3f(1.0, 1.0, 0.0);
 
 
 
 i := 0;
 r := 0.25;
 x := 0;
 y := 0;
 
 segments_amount := 32;
 glBegin(GL_LINE_LOOP);
 for i := 0 to segments_amount do begin
 angle := 2.0 * 3.1415926 * i / segments_amount;
 dx := r * cos(angle);
 dy := r * sin(angle);
 glVertex2f(x + dx, y + dy);
 end;
 glEnd();
 
 r := r/2;
 glBegin(GL_LINE_LOOP);
 for i := 0 to segments_amount do begin
 angle := 2.0 * 3.1415926 * i / segments_amount;
 dx := r * cos(angle);
 dy := r * sin(angle);
 glVertex2f(x + dx, y + dy);
 end;
 glEnd();
 
 
 
 swapBuffers(dc_window); // put opengl stuff to screen
 end;
 
 
 procedure throw_error(pcErrorMessage : pchar);
 begin
 messageBox(0, pcErrorMessage, 'Error', MB_OK);
 halt(0);
 end;
 
 
 { Функция обработки сообщений}
 function wnd_proc(window: hwnd; amessage, wparam, lparam: longint): longint; stdcall; export;
 begin
 result := 0;
 case amessage of
 WM_CREATE:
 begin
 active := true; // if GL Window was created correctly, then set
 exit; // active-flag to "true".
 end;
 
 WM_PAINT:
 begin
 gl_render();
 exit; // nothing to paint to Windows as we do all drawing with OGL
 end;
 
 WM_SIZE:
 begin
 gl_resize(LOWORD(lparam), HIWORD(lparam));
 gl_render();
 active := true;
 exit;
 end;
 
 WM_MOVE:
 begin
 exit;
 end;
 
 WM_ERASEBKGND:
 begin
 exit; // чтобы не перезаливалось окно и не было мерцания
 end;
 WM_KEYDOWN:
 begin
 if wparam = VK_ESCAPE then
 sendMessage(hwindow, wm_destroy,0,0);
 exit; // check for ESC key. If pressed, then send quit message
 end;
 WM_DESTROY:
 begin
 active := false; // if quit message was sent, exit the main loop by setting
 postQuitMessage(0); // the active-flag to "false".
 kill_gl_window();
 exit;
 end;
 WM_SYSCOMMAND: // system wants something..
 begin
 case (wparam) of
 SC_SCREENSAVE : begin // ..don't start any screensavers.
 result := 0;
 end;
 SC_MONITORPOWER : begin // ..and don't kill monitor power.
 result := 0;
 end;
 end;
 end;
 
 WM_GETMINMAXINFO:
 begin
 with pMinMaxInfo(lparam)^ do begin
 ptMinTrackSize.x := 800;
 ptMinTrackSize.y := 600;
 end;
 exit;
 end;
 
 end;
 result := defWindowProc(window, amessage, wparam, lparam); // let Windows deal with the rest of the messages.
 end;
 
 function register_window: boolean;
 var
 window_class : wndClass;
 begin
 window_class.style := CS_HREDRAW or CS_VREDRAW;
 window_class.lpfnWndProc := wndProc(@wnd_proc); // Handle to our Windows messaging interface func.
 window_class.cbClsExtra := 0;
 window_class.cbWndExtra := 0;
 window_class.hInstance := system.mainInstance; // Get the Windows Instance for our app.
 window_class.hIcon := loadIcon(0, IDI_APPLICATION);
 window_class.hCursor := loadCursor(0, IDC_ARROW);
 window_class.hbrBackground := getStockObject(WHITE_BRUSH);
 window_class.lpszMenuName := nil;
 window_class.lpszClassName := 'GLWindow'; // Name the specified Window Class
 
 result := registerClass(window_class) <> 0;
 end;
 { Создаём пустое окно }
 function create_empty_window(app_name : pchar; visible : boolean = true): hwnd;
 var
 hwindow: hwnd; // Handle to Window
 //dmScreenSettings : DEVMODE; // Used for Full Screen Mode
 begin
 hwindow := createWindow('GLWindow',
 app_name,
 WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN or WS_CLIPSIBLINGS,
 cw_useDefault,
 cw_useDefault,
 width,
 height,
 0, 0,
 system.mainInstance,
 nil);
 if hwindow <> 0 then
 begin
 if visible then begin
 showWindow(hwindow, CmdShow);
 updateWindow(hwindow);
 end;
 end;
 create_empty_window := hwindow;
 end;
 
 
 { Init the Window and bind OGL to it. }
 function init_window(hparent : hwnd): boolean;
 var
 function_error : integer;
 pfd : PIXELFORMATDESCRIPTOR;
 iformat : integer; // Pixel Format
 begin
 function_error := 0;
 dc_window := getDC( hParent ); // Get Device Context
 fillChar(pfd, sizeof(pfd), 0); // Define Pixel Format
 pfd.nSize := sizeof(pfd);
 pfd.nVersion := 1;
 pfd.dwFlags := PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER;
 pfd.iPixelType := PFD_TYPE_RGBA;
 pfd.cColorBits := 32;
 pfd.cDepthBits := 32;
 pfd.iLayerType := PFD_MAIN_PLANE;
 iformat := choosePixelFormat(dc_window, @pfd); // Create Pixel Format
 if (iformat = 0) then
 function_error := 1;
 setPixelFormat(dc_window, iformat, @pfd); // Set Pixel Format
 rc_window := wglCreateContext(dc_window); // Create OpenGL Context
 if (rc_window = 0) then
 function_error := 2;
 wglMakeCurrent(dc_window, rc_window); // Bind OpenGL to our Window
 if function_error = 0 then
 init_window := true
 else
 init_window := false;
 end;
 
 
 { Kill Application Window again. }
 procedure kill_gl_window();
 begin
 wglMakeCurrent(dc_window, 0); // Kill Device Context
 wglDeleteContext(rc_window); // Kill Render Context
 releaseDC(hWindow, dc_window); // Release Window
 destroyWindow(hwindow); // Kill Window itself
 end;
 
 { ***************************************************************************************************** }
 
 procedure process_messages();
 begin
 repeat // start main proc
 if peekMessage(@msg,0,0,0,0) = true then
 begin
 getMessage(@msg,0,0,0);
 translateMessage(msg);
 dispatchMessage(msg);
 end;
 until active = false; // end main proc
 end;
 
 
 function create_gl_window(app_name : pchar; wnd_width, wnd_height : longint; app_fullscreen : boolean) : boolean;
 begin
 width := wnd_width;
 height := wnd_height;
 fullscreen := app_fullscreen;
 if not register_window() then begin
 throw_error('Could not register the Application Window!');
 result := false;
 exit;
 end;
 hwindow := create_empty_window(app_name);
 if longint(hwindow) = 0 then begin
 throw_error('Could not create Application Window!');
 result := false;
 exit;
 end;
 if not init_window(hwindow) then begin
 throw_error('Could not initialise Application Window!');
 result := false;
 exit;
 end;
 
 gl_init();
 result := true;
 end;
 
 end.
А вот сюда бы передать управление, чтобы обрабатывать все события от кона, нажатия клавиш на клавиатуре и обработку мыши:
- Код: Выделить всё
- {$mode objfpc}{$h+}
 unit tr_core;
 interface
 uses
 tr_application;
 type
 TCore = class
 private
 fapp : tapplication;
 fscene_width : integer;
 fscene_height : integer;
 
 public
 constructor create();
 destructor destroy();
 
 procedure on_key_pressed(key : integer);
 procedure on_key_released(key : integer);
 
 procedure on_mouse_move(x : integer; y : integer);
 procedure on_mouse_down(x : integer; y : integer; button : integer);
 procedure on_mouse_up(x : integer; y : integer; button : integer);
 procedure on_double_click(x : integer; y : integer; button : integer);
 procedure on_mouse_wheel(dx : integer; dy : integer);
 procedure on_resize(width : integer; height : integer);
 
 procedure render();
 
 end;
 implementation
 
 constructor TCore.create();
 begin
 
 end;
 
 
 destructor TCore.destroy();
 begin
 
 end;
 
 
 procedure TCore.on_key_pressed(key : integer);
 begin
 
 end;
 
 . . .
 
 
 procedure TCore.render();
 begin
 
 end;
 end.
Ну и основной код прилоежения:
- Код: Выделить всё
- program ttt;
 uses
 tr_application;
 var
 app : tapplication;
 begin
 app := tapplication.get_instance();
 app.create_window('', 1024, 768, false);
 app.main_loop();
 
 app.destroy();
 end.
У кого какие мысли?










