diff --git a/intern/ant/ANT_gdi.pas b/intern/ant/ANT_gdi.pas index 72eda5d..a880d9d 100644 --- a/intern/ant/ANT_gdi.pas +++ b/intern/ant/ANT_gdi.pas @@ -10,6 +10,9 @@ interface MEM_guardedalloc, ANT_base, ANT_types; +function gdi_Init: boolean; +function gdi_Terminate: boolean; + { Creates a GDI window and its associated context. @param Width: the width of the window @@ -17,12 +20,15 @@ interface @param title: the title of the window @return a reference to the created window } -function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; +function gdi_CreateWindow(win: pANTwindow; posx, posy, sizex, sizey: integer; title: PChar): boolean; { Destroys a GDI window and its associated context. @param win: the reference to the window being destroyed } procedure gdi_DestroyWindow(var win: pANTwindow); + +function gdi_MakeCurrent(win: pANTwindow): boolean; + { Swaps the front and back buffers of the specified window. @param win: the reference to the window @@ -43,37 +49,25 @@ procedure gdi_GetFrameBufferSize(win: pANTwindow; out width, height: integer); } procedure gdi_PollEvents; +procedure gdi_GetDisplayCoords(var dr: ANTRect); + implementation uses SysUtils, ANT_main, ANT_messages; +var + wc: TWndclass; + h_Instance: HINST; + function gdi_WindowFromHWND(hWnd: Windows.HWND): pANTwindow; forward; function gdi_GetKeyboardShiftState: TShiftState; forward; function WndProc(hWnd: Windows.HWND; message: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; forward; -function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; -const - bits = 16; -var - Pixelformat: GLuint; - wc: TWndclass; - dwExStyle: dword; - dwStyle: dword; - pfd: pixelformatdescriptor; - dmScreenSettings: Devmode; - WindowRect: TRect; - win: pANTwindow = nil; +function gdi_Init: boolean; begin - win := callocN(sizeof(ANTWindow), 'ANTWindow'); - - WindowRect.Left := 0; - WindowRect.Top := 0; - WindowRect.Right := Width; - WindowRect.Bottom := Height; - - win^.h_Instance := GetModuleHandle(nil); + h_Instance := GetModuleHandle(nil); with wc do begin @@ -81,20 +75,60 @@ function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; lpfnWndProc := @WndProc; cbClsExtra := 0; cbWndExtra := 0; - hInstance := win^.h_Instance; + hInstance := h_Instance; hIcon := LoadIcon(0, IDI_WINLOGO); hCursor := LoadCursor(0, IDC_ARROW); hbrBackground := 0; lpszMenuName := nil; - lpszClassName := 'ANT'; + lpszClassName := 'ANT class'; end; if RegisterClass(wc) = 0 then begin - antError(ANT_PLATFORM_ERROR, 'ANT error: failed to register the window class', []); - exit(nil); + case GetLastError of + ERROR_CLASS_ALREADY_EXISTS: + antError(ANT_PLATFORM_ERROR, 'ANT error: class already exists', []); + ERROR_CLASS_DOES_NOT_EXIST: + antError(ANT_PLATFORM_ERROR, 'ANT error: class does not exists', []); + ERROR_CLASS_HAS_WINDOWS: + antError(ANT_PLATFORM_ERROR, 'ANT error: class has windows', []); + else + antError(ANT_PLATFORM_ERROR, 'ANT error: unknown class error', []); + end; + + exit(False); end; + exit(True); +end; + +function gdi_Terminate: boolean; +begin + if (not UnregisterClass('ANT class', h_Instance)) then + begin + antError(ANT_PLATFORM_ERROR, 'ANT error: could not unregister class', []); + exit(False); + end; + + exit(True); +end; + +function gdi_CreateWindow(win: pANTwindow; posx, posy, sizex, sizey: integer; title: PChar): boolean; +const + bits = 16; +var + Pixelformat: GLuint; + dwExStyle: dword; + dwStyle: dword; + pfd: pixelformatdescriptor; + dmScreenSettings: Devmode; + WindowRect: TRect; +begin + WindowRect.Left := posx; + WindowRect.Top := posy; + WindowRect.Right := sizex; + WindowRect.Bottom := sizey; + if win^.fscreen then begin ZeroMemory(@dmScreenSettings, sizeof(dmScreenSettings)); @@ -129,7 +163,7 @@ function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; AdjustWindowRectEx(WindowRect, dwStyle, False, dwExStyle); win^.h_Wnd := CreateWindowEx(dwExStyle, - 'ANT', + 'ANT class', Title, dwStyle, 0, 0, @@ -143,7 +177,7 @@ function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; begin gdi_DestroyWindow(win); antError(ANT_PLATFORM_ERROR, 'ANT error: window creation error', []); - exit(nil); + exit(False); end; with pfd do @@ -180,7 +214,7 @@ function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; begin gdi_DestroyWindow(win); antError(ANT_PLATFORM_ERROR, 'ANT error: can''t create a GL device context', []); - exit(nil); + exit(False); end; PixelFormat := ChoosePixelFormat(win^.h_DC, @pfd); @@ -188,14 +222,14 @@ function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; begin gdi_DestroyWindow(win); antError(ANT_PLATFORM_ERROR, 'ANT error: can''t find a suitable PixelFormat', []); - exit(nil); + exit(False); end; if not SetPixelFormat(win^.h_DC, PixelFormat, @pfd) then begin gdi_DestroyWindow(win); antError(ANT_PLATFORM_ERROR, 'ANT error: can''t set PixelFormat', []); - exit(nil); + exit(False); end; win^.h_RC := wglCreateContext(win^.h_DC); @@ -203,14 +237,14 @@ function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; begin gdi_DestroyWindow(win); antError(ANT_PLATFORM_ERROR, 'ANT error: can''t create a GL rendering context', []); - exit(nil); + exit(False); end; if not wglMakeCurrent(win^.h_DC, win^.h_RC) then begin gdi_DestroyWindow(win); antError(ANT_PLATFORM_ERROR, 'ANT error: can''t activate the GL rendering context', []); - exit(nil); + exit(False); end; ShowWindow(win^.h_Wnd, SW_SHOW); @@ -218,7 +252,7 @@ function gdi_CreateWindow(Width, Height: integer; title: PChar): pANTwindow; SetFocus(win^.h_Wnd); addtail(@windowlist, win); - exit(win); + exit(True); end; procedure gdi_DestroyWindow(var win: pANTwindow); @@ -253,11 +287,11 @@ procedure gdi_DestroyWindow(var win: pANTwindow); antError(ANT_PLATFORM_ERROR, 'ANT error: could not release hWnd', []); win^.h_Wnd := 0; end; +end; - if (not UnregisterClass('ANT', win^.h_Instance)) then - begin - antError(ANT_PLATFORM_ERROR, 'ANT error: could not unregister class', []); - end; +function gdi_MakeCurrent(win: pANTwindow): boolean; +begin + exit(wglMakeCurrent(win^.h_DC, win^.h_RC)); end; procedure gdi_SwapBuffers(win: pANTwindow); @@ -287,6 +321,17 @@ procedure gdi_PollEvents; end; end; +procedure gdi_GetDisplayCoords(var dr: ANTRect); +begin + if not SystemParametersInfo(SPI_GETWORKAREA, 0, @dr, 0) then + begin + dr.right := 0; + dr.left := 0; + dr.bottom := 0; + dr.top := 0; + end; +end; + function gdi_WindowFromHWND(hWnd: Windows.HWND): pANTwindow; var wi: pANTwindow; @@ -300,6 +345,8 @@ function gdi_WindowFromHWND(hWnd: Windows.HWND): pANTwindow; wi := wi^.next; end; + + exit(nil); end; function gdi_GetKeyboardShiftState: TShiftState; @@ -409,11 +456,15 @@ function WndProc(hWnd: Windows.HWND; message: UINT; wParam: WPARAM; lParam: LPAR antPostMessage(win, ANT_MESSAGE_RESIZE, params); end; - + //WM_PAINT: + // antPostMessage(win, ANT_MESSAGE_PAINT, params); else begin //writeln(message); + if message = WM_PAINT then + antPostMessage(win, ANT_MESSAGE_PAINT, params); + exit(DefWindowProc(hWnd, message, wParam, lParam)); end; end; diff --git a/intern/ant/ANT_main.pas b/intern/ant/ANT_main.pas index 4bf0474..9287e0c 100644 --- a/intern/ant/ANT_main.pas +++ b/intern/ant/ANT_main.pas @@ -32,14 +32,16 @@ interface @return True is successfull otherwise False } function ANT_Init: boolean; + { Terminates the ANT library } -procedure ANT_Terminate; +function ANT_Terminate: boolean; function ANT_WindowShouldClose(win: pANTwindow): boolean; procedure ANT_SetWindowShouldClose(win: pANTwindow; value: boolean); + { Creates a window and its associated context. @param Width: the width of the window @@ -47,17 +49,22 @@ procedure ANT_SetWindowShouldClose(win: pANTwindow; value: boolean); @param title: the title of the window @return a reference to the created window } -function ANT_CreateWindow(width, height: integer; title: PChar): pANTwindow; +function ANT_CreateWindow(posx, posy, sizex, sizey: integer; title: PChar): pANTwindow; + { Destroys a window and its associated context. @param win: the reference to the window being destroyed } procedure ANT_DestroyWindow(win: pANTwindow); + +function ANT_MakeCurrent(var win: pANTwindow): boolean; + { Swaps the front and back buffers of the specified window. @param win: the reference to the window } procedure ANT_SwapBuffers(win: pANTwindow); + { Retrieves the size of the framebuffer of the specified window. @param win: the reference to the window @@ -71,11 +78,7 @@ procedure ANT_GetFrameBufferSize(win: pANTwindow; out width, height: integer); @param pointer to error callback: } procedure ANT_SetErrorCallback(errorCallback: ANT_ErrorCallback); -{ - Sets the event callback procedure - @param pointer to event callback: -} -procedure ANT_SetEventCallback(eventCallback: ANT_EventCallback); + { This is the procedure will poll for any pending events and put them in the eventlist. Next the eventlist is checked and if needed the event @@ -83,6 +86,10 @@ procedure ANT_SetEventCallback(eventCallback: ANT_EventCallback); } procedure ANT_PollEvents; +procedure ANT_SetCursor(cursor: byte); + +procedure ANT_GetDisplayCoords(var dr: ANTRect); + implementation uses @@ -99,10 +106,10 @@ implementation function ANT_Init: boolean; begin - exit(True); + exit(gdi_Init); end; -procedure ANT_Terminate; +function ANT_Terminate: boolean; var win: pANTwindow; begin @@ -115,6 +122,8 @@ procedure ANT_Terminate; win := win^.next; end; + + exit(gdi_Terminate); end; function ANT_WindowShouldClose(win: pANTwindow): boolean; @@ -127,14 +136,27 @@ procedure ANT_SetWindowShouldClose(win: pANTwindow; value: boolean); win^.shouldClose := value; end; -function ANT_CreateWindow(width, height: integer; title: PChar): pANTwindow; +function ANT_CreateWindow(posx, posy, sizex, sizey: integer; title: PChar): pANTwindow; +var + win: pANTwindow = nil; + res: boolean = False; begin + win := callocN(sizeof(ANTWindow), 'ANTWindow'); + {$IFDEF MSWINDOWS} - exit(gdi_CreateWindow(width, height, title)); + res := gdi_CreateWindow(win ,posx, posy, sizex, sizey, title); {$ENDIF} {$IFDEF LINUX} - exit(X11_CreateWindow(width, height, title)); + res := X11_CreateWindow(win, posx, posy, sizex, sizey, title); {$ENDIF} + + if res then + exit(win) + else + begin + freeN(win); + exit(nil); + end; end; procedure ANT_DestroyWindow(win: pANTwindow); @@ -151,6 +173,11 @@ procedure ANT_DestroyWindow(win: pANTwindow); freeN(win); end; +function ANT_MakeCurrent(var win: pANTwindow): boolean; +begin + exit(gdi_MakeCurrent(win)); +end; + procedure ANT_SwapBuffers(win: pANTwindow); begin {$IFDEF MSWINDOWS} @@ -176,14 +203,10 @@ procedure ANT_SetErrorCallback(errorCallback: ANT_ErrorCallback); errfunc := errorCallback; end; -procedure ANT_SetEventCallback(eventCallback: ANT_EventCallback); -begin - eventfunc := eventCallback; -end; - procedure ANT_PollEvents; var event: pANT_MessageRec; + win: pANTwindow; begin {$IFDEF MSWINDOWS} gdi_PollEvents; @@ -192,17 +215,32 @@ procedure ANT_PollEvents; X11_PollEvents; {$ENDIF} - if eventfunc <> nil then - begin - event := antReadLastMessage; + event := antReadFirstMessage; - if event <> nil then - begin - eventfunc(event); + if event <> nil then + begin + win := event^.win; + if win > nil then + if win^.event_callback <> nil then + win^.event_callback(event); - antDeleteMessage(event); - end; + antDeleteMessage(event); end; end; +procedure ANT_SetCursor(cursor: byte); +begin + {$note implement this} +end; + +procedure ANT_GetDisplayCoords(var dr: ANTRect); +begin +{$IFDEF MSWINDOWS} + gdi_GetDisplayCoords(dr); +{$ENDIF} +{$IFDEF LINUX} + x11_GetDisplayCoords(dr); +{$ENDIF} +end; + end. diff --git a/intern/ant/ANT_messages.pas b/intern/ant/ANT_messages.pas index 518e98e..1bbc729 100644 --- a/intern/ant/ANT_messages.pas +++ b/intern/ant/ANT_messages.pas @@ -91,35 +91,38 @@ ANT_MessageRec = record @param MsgCode: message code @param Params: event data } -procedure antPostMessage(Window: pANTwindow; MsgCode: integer; Params: ANT_MessageParams); +procedure antPostMessage(win: pANTwindow; MsgCode: integer; Params: ANT_MessageParams); { Reads the last mesage from the queue @return The last message from the queue, otherwise nil. } function antReadLastMessage: pANT_MessageRec; +{ + Reads the first mesage from the queue + @return The first message from the queue, otherwise nil. +} +function antReadFirstMessage: pANT_MessageRec; { Deletes message from the queue @param msg: message to be deleted } procedure antDeleteMessage(msg: pANT_MessageRec); -var - eventfunc: ANT_EventCallback = nil; - implementation var msglist: ListBase; -procedure antPostMessage(Window: pANTwindow; MsgCode: integer; Params: ANT_MessageParams); +procedure antPostMessage(win: pANTwindow; MsgCode: integer; Params: ANT_MessageParams); var msg: pANT_MessageRec; begin msg := callocN(sizeof(ANT_MessageRec), 'ANT_Message'); + msg^.win := win; + msg^.mcode := MsgCode; move(Params, msg^.params, sizeof(ANT_MessageParams)); - msg^.win := Window; addtail(@msglist, msg); end; @@ -129,10 +132,15 @@ function antReadLastMessage: pANT_MessageRec; exit(msglist.last); end; +function antReadFirstMessage: pANT_MessageRec; +begin + exit(msglist.first); +end; + procedure antDeleteMessage(msg: pANT_MessageRec); begin remlink(@msglist, msg); - freeN(msg); + freeN(msg); end; end. diff --git a/intern/ant/ANT_types.pas b/intern/ant/ANT_types.pas index 4cd7a80..d475d33 100644 --- a/intern/ant/ANT_types.pas +++ b/intern/ant/ANT_types.pas @@ -215,6 +215,13 @@ interface ANT_EventCallback = procedure(msg: pointer); ANT_ErrorCallback = procedure(error: integer; const description: string); + ANTRect = record + left: longint; + top: longint; + right: longint; + bottom: longint; + end; + pANTwindow = ^ANTwindow; ANTWindow = record @@ -226,12 +233,13 @@ ANTWindow = record fscreen: boolean; //< Flag that indictes if the window is fullscreen or not shouldClose: boolean; //< Flag indicating if the window should close + //callback functions + event_callback: ANT_EventCallback; //< event callback function for this window + {$IFDEF MSWINDOWS} - wc: TWndclass; //< GDI window class h_Wnd: Windows.HWND; //< GDI window handle h_DC: Windows.HDC; //< GDI device context h_RC: HGLRC; //< GDI rendering context - h_Instance: HINST; //< GDI application instance {$ENDIF} {$IFDEF LINUX} dpy: pDisplay; //< X11 display diff --git a/intern/ant/examples/gears.pp b/intern/ant/examples/gears.pp index 558b1c9..b518cdb 100644 --- a/intern/ant/examples/gears.pp +++ b/intern/ant/examples/gears.pp @@ -301,12 +301,13 @@ end; ANT_SetErrorCallback(@error_callback); - ANT_SetEventCallback(@event_callback); if not ANT_Init then halt(-1); - win := ANT_CreateWindow(640, 480, 'Gears'); + win := ANT_CreateWindow(0, 0, 640, 480, 'Gears'); + + win^.event_callback := @event_callback; init; diff --git a/intern/ant/examples/simple.pp b/intern/ant/examples/simple.pp index b7a4dcc..2f9a011 100644 --- a/intern/ant/examples/simple.pp +++ b/intern/ant/examples/simple.pp @@ -69,7 +69,7 @@ procedure event_callback(msg: pointer); if not ANT_Init then halt(-1); - window := ANT_CreateWindow(width, height, 'Simple example'); + window := ANT_CreateWindow(0, 0, width, height, 'Simple example'); if window = nil then begin ANT_Terminate; @@ -78,7 +78,7 @@ procedure event_callback(msg: pointer); ratio := width / height; - ANT_SetEventCallback(@event_callback); + window^.event_callback := @event_callback; writeln('OpenGL version: ', glGetString(GL_VERSION)); diff --git a/intern/ant/examples/two_windows.pp b/intern/ant/examples/two_windows.pp new file mode 100644 index 0000000..82543f5 --- /dev/null +++ b/intern/ant/examples/two_windows.pp @@ -0,0 +1,135 @@ +program two_windows; + +uses + SysUtils, + GL, + DNA_listbase, + ANT_main, ANT_types, ANT_messages; + +var + win1, win2: pANTWindow; + ratio: double; + width: integer = 640; + height: integer = 480; + nbFrames: longint = 0; + lastTime: double; + rotate: double; + +procedure setWindowFPS; +var + currentTime: double; + title: string; +begin + // measure FPS + currentTime := Now * 24 * 3600; + inc(nbFrames); + + if currentTime - lastTime >= 1 then + begin + title := format('[FPS: %3.0f]', [nbFrames/(currentTime - lastTime)]); + + writeln(title); + + nbFrames := 0; + lastTime := Now * 24 * 3600; + end; +end; + +procedure error_callback(error : integer; + const description : string); +begin + writeln(stderr, description); +end; + +procedure event_callback(msg: pointer); +var + event: pANT_MessageRec; +begin + event := msg; + + case event^.mcode of + ANT_MESSAGE_KEYPRESS: + begin + writeln(event^.params.keyboard.keychar); + + if event^.params.keyboard.keychar = ANT_KEY_ESCAPE then + ANT_SetWindowShouldClose(event^.win, True); + end; + ANT_MESSAGE_MOUSEDOWN: + begin + writeln(event^.params.mouse.buttons); + end; + end; +end; + +procedure draw(win: pANTWindow); +begin + ANT_MakeCurrent(win); + + glViewport(0, 0, width, height); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity; + glOrtho(-ratio, ratio, -1, 1, 1, -1); + glMatrixMode(GL_MODELVIEW); + + glLoadIdentity; + rotate := Now * 24 * 3600 * 60; + rotate := rotate - int(rotate / 360) * 360; + + glRotatef(rotate, 0, 0, 1); + + glBegin(GL_TRIANGLES); + glColor3f(1, 0, 0); + glVertex3f(-0.6, -0.4, 0); + glColor3f(0, 1, 0); + glVertex3f(0.6, -0.4, 0); + glColor3f(0, 0, 1); + glVertex3f(0, 0.6, 0); + glEnd; + + ANT_SwapBuffers(win); +end; + +begin + ANT_SetErrorCallback(@error_callback); + + if not ANT_Init then + halt(-1); + + //main window + win1 := ANT_CreateWindow(0, 0, width, height, 'Simple example 1'); + if win1 = nil then + begin + ANT_Terminate; + halt(-1); + end; + + win2 := ANT_CreateWindow(0, 0, width, height, 'Simple example 2'); + if win2 = nil then + begin + ANT_Terminate; + halt(-1); + end; + + ratio := width / height; + + win1^.event_callback := @event_callback; + + writeln('OpenGL version: ', glGetString(GL_VERSION)); + + while not ANT_WindowShouldClose(win1) do + begin + setWindowFPS; + + draw(win1); + draw(win2); + + ANT_PollEvents; + end; + + ANT_DestroyWindow(win1); + + ANT_Terminate; +end.