| Description | Hierarchy | Fields | Methods | Properties |
type TGLWindow = class(TObject)
Small helpful utilities for GLWindow implementations that are based on a system where left shift and right shift keys (or Alt, or Ctrl keys) are given as different keys. This situation requires some special care because in our TKey type (and so in TGLWindow.KeysDown table) we do not differentiate between right and left Shift key (or Alt, or Ctrl).
Currently this concerns GTK and Xlib implementations.
If you want to use this file in some GLWindow implementation, define GLWINDOW_USE_PRIVATE_MODIFIERS_DOWN when compiling that implementation. It is important to define GLWINDOW_USE_PRIVATE_MODIFIERS_DOWN instead of simply including this file in GLWindow-implementation-specific file, because this allows ReleaseAllKeysAndMouse to use some special code when GLWINDOW_USE_PRIVATE_MODIFIERS_DOWN.
Then you have to call SetPrivateModifiersDown with appropriate arguments at appropriate times. And that's all. SetPrivateModifiersDown will take care of calling DoKeyDown(k) and DoKeyUp(k) for you for k = K_Shift, K_Ctrl, K_Alt.
![]() |
OnInitList: TDynGLWindowFuncArray; |
![]() |
MinWidth: integer; |
![]() |
MinHeight: integer; |
![]() |
MaxWidth: integer; |
![]() |
MaxHeight: integer; |
![]() |
AccumBufferBits: TVector4Cardinal; |
![]() |
OnCloseList: TDynGLWindowFuncArray; |
![]() |
OnKeyDown: TKeyCharFunc; |
![]() |
OwnsMainMenu: boolean; |
![]() |
OnMenuCommand: TMenuCommandFunc; |
![]() |
UserData: Pointer; |
![]() |
KeysDown: TKeysBooleans; |
![]() |
function MakeGLAreaContainer(GLArea: PGtkGLArea): PGtkWidget; virtual; |
![]() |
procedure EventResize; virtual; |
![]() |
procedure EventInit; virtual; |
![]() |
procedure EventClose; virtual; |
![]() |
function EventCloseQuery: boolean; virtual; |
![]() |
procedure EventDraw; virtual; |
![]() |
procedure EventBeforeDraw; virtual; |
![]() |
procedure EventKeyDown(Key: TKey; c: char); virtual; |
![]() |
procedure EventKeyUp(key: TKey); virtual; |
![]() |
procedure EventMouseMove(newX, newY: integer); virtual; |
![]() |
procedure EventMouseDown(btn: TMouseButton); virtual; |
![]() |
procedure EventMouseUp(btn: TMouseButton); virtual; |
![]() |
procedure EventIdle; virtual; |
![]() |
procedure EventTimer; virtual; |
![]() |
procedure EventMenuCommand(Item: TMenuItem); virtual; |
![]() |
function AllowsProcessMessageSuspend: boolean; virtual; |
![]() |
procedure SetMousePosition(const NewMouseX, NewMouseY: Integer); |
![]() |
procedure Init; |
![]() |
procedure Close(QuitWhenLastWindowClosed: boolean = true); |
![]() |
procedure PostRedisplay; |
![]() |
procedure FlushRedisplay; |
![]() |
procedure MakeCurrent; |
![]() |
procedure SaveScreen(const fname: string); overload; |
![]() |
function SaveScreen: TRGBImage; overload; |
![]() |
function SaveScreen( const xpos, ypos, SavedAreaWidth, SavedAreaHeight: integer): TRGBImage; overload; |
![]() |
function SaveScreenToDisplayList: TGLuint; overload; |
![]() |
function SaveScreenToDisplayList(const xpos, ypos, SavedAreaWidth, SavedAreaHeight: integer): TGLuint; overload; |
![]() |
procedure SaveScreenDialog(ProposedFileName: string); |
![]() |
function GetCallbacksState: TGLWindowCallbacks; |
![]() |
procedure SetCallbacksState(const Callbacks: TGLWindowCallbacks); |
![]() |
constructor Create; |
![]() |
destructor Destroy; override; |
![]() |
function ModifiersDown: TModifierKeys; |
![]() |
function FpsFrameTime: Double; |
![]() |
function FpsRealTime: Double; |
![]() |
procedure FpsToCaption(const WindowTitle: string); |
![]() |
procedure FpsReset; |
![]() |
procedure InitLoop; overload; |
![]() |
procedure InitLoop(const ACaption: string; AOnDraw: TDrawFunc); overload; |
![]() |
procedure ParseParameters(); overload; |
![]() |
procedure ParseParameters(const AllowedOptions: TGLWindowParseOptions); overload; |
![]() |
procedure ParseParameters(const AllowedOptions: TGLWindowParseOptions; out SpecifiedOptions: TGLWindowParseOptions); overload; |
![]() |
class function ParseParametersHelp( const AllowedOptions: TGLWindowParseOptions; AddHeader: boolean): string; |
![]() |
function FileDialog(const Title: string; var FileName: string; OpenDialog: boolean): boolean; |
![]() |
function ColorDialog(var Color: TVector3Single): boolean; |
![]() |
property BorderWidth: Cardinal
read FBorderWidth write FBorderWidth default 0; |
![]() |
property Width: integer read FWidth write FWidth default GLWindowDefaultSize; |
![]() |
property Height: integer read FHeight write FHeight default GLWindowDefaultSize; |
![]() |
property Left: integer read FLeft write FLeft; |
![]() |
property Top : integer read FTop write FTop; |
![]() |
property FullScreen: boolean read FFullScreen write FFullScreen; |
![]() |
property DoubleBuffer: boolean read FDoubleBuffer write FDoubleBuffer default true; |
![]() |
property ColorBits: integer
read FColorBits write FColorBits default 0; |
![]() |
property Cursor: TGLWindowCursor read FCursor write SetCursor default gcDefault; |
![]() |
property CustomCursor: TAlphaImage read FCustomCursor
write SetCustomCursor; |
![]() |
property ResizeAllowed: TResizeAllowed read FResizeAllowed write FResizeAllowed; |
![]() |
property OnInit: TGLWindowFunc read FOnInit write FOnInit; |
![]() |
property DepthBufferBits: Cardinal
read FDepthBufferBits write FDepthBufferBits default DefaultDepthBufferBits; |
![]() |
property StencilBufferBits: Cardinal
read FStencilBufferBits write FStencilBufferBits default 0; |
![]() |
property MultiSampling: Cardinal
read FMultiSampling write FMultiSampling default 1; |
![]() |
property AlphaBits: Cardinal
read FAlphaBits write FAlphaBits default 0; |
![]() |
property Caption: string read FCaption write SetCaption; |
![]() |
property OnDraw: TDrawFunc read FOnDraw write FOnDraw; |
![]() |
property OnBeforeDraw: TDrawFunc read FOnBeforeDraw write FOnBeforeDraw; |
![]() |
property OnResize: TGLWindowFunc read FOnResize write FOnResize; |
![]() |
property OnClose: TGLWindowFunc read FOnClose write FOnClose; |
![]() |
property OnKeyUp: TKeyFunc read FOnKeyUp write FOnKeyUp; |
![]() |
property OnCloseQuery: TGLWindowFunc read FOnCloseQuery write FOnCloseQuery; |
![]() |
property OnMouseMove : TMouseMoveFunc read FMouseMove write FMouseMove; |
![]() |
property OnMouseDown : TMouseUpDownFunc
read FMouseDown write FMouseDown ; |
![]() |
property OnMouseUp : TMouseUpDownFunc
read FMouseUp write FMouseUp ; |
![]() |
property OnIdle: TGLWindowFunc read FOnIdle write FOnIdle; |
![]() |
property OnTimer: TGLWindowFunc read FOnTimer write FOnTimer; |
![]() |
property AutoRedisplay: boolean read fAutoRedisplay write SetAutoRedisplay; |
![]() |
property MainMenu: TMenu read FMainMenu write SetMainMenu; |
![]() |
property MousePressed: TMouseButtons read FMousePressed; |
![]() |
property MouseX: integer read FMouseX; |
![]() |
property MouseY: integer read FMouseY; |
![]() |
property Closed: boolean read FClosed; |
![]() |
property FpsActive: boolean read FFpsActive write SetFpsActive; |
![]() |
property FpsSecondsToAutoReset: Cardinal
read FFpsSecondsToAutoReset
write FFpsSecondsToAutoReset; |
![]() |
property FpsHoldsAfterReset: DWORD
read FFpsHoldsAfterReset
write FFpsHoldsAfterReset; |
![]() |
property FpsCompSpeed: Single read FFpsCompSpeed; |
![]() |
property IdleCompSpeed: Single read FIdleCompSpeed; |
![]() |
OnInitList: TDynGLWindowFuncArray; |
|
zawsze po wywolaniu OnInit beda wywolywane wszystkie funkcje z listy | |
![]() |
MinWidth: integer; |
|
minimalne i maksymalne rozmiary okna. Musi byc 0 < Jesli sprobujesz samemu zainicjowac Width lub Height okienka na cos spoza tego zakresu - jesli to bedzie mniejsze od Tym sposobem ZAWSZE bedzie zachodzic | |
![]() |
MinHeight: integer; |
|
minimalne i maksymalne rozmiary okna. Musi byc 0 < minWidth <= maxWidth, 0 < Jesli sprobujesz samemu zainicjowac Width lub Height okienka na cos spoza tego zakresu - jesli to bedzie mniejsze od minWidth to zostanie przyjete minWidth, jesli wieksze od maxWidth - zostanie przyjete maxWidth (tzn. zostanie poprawione dopiero w Init !). Bedzie to wykonane nawet jesli ResizeAllowed = raNotAllowed ! Wiec pamietaj ze jesli chcesz zeby ResizeAllowed = raNotAllowed bylo honorowane - width i height musza sie zawierac w min/max Width/Height. Podobnie, jezeli ustawisz Fullscreen := true i okaze sie ze rozmiary ekranu sa zle - flaga FullScreen zostanie wylaczona. Innymi slowy, niniejsze ograniczenia maja priorytet ponad ResizeAllowed, a wszystkie razem (min/maxWidth/Height i ResizeAllowed) maja priorytet nad Width, Height, FullScreen. Tym sposobem ZAWSZE bedzie zachodzic minWidth <= width <= maxWidth, o ile tylko not Closed. I wszystko co napisalem dziala tak samo dla Height. | |
![]() |
MaxWidth: integer; |
|
minimalne i maksymalne rozmiary okna. Musi byc 0 < minWidth <= Jesli sprobujesz samemu zainicjowac Width lub Height okienka na cos spoza tego zakresu - jesli to bedzie mniejsze od minWidth to zostanie przyjete minWidth, jesli wieksze od Tym sposobem ZAWSZE bedzie zachodzic minWidth <= width <= | |
![]() |
MaxHeight: integer; |
|
minimalne i maksymalne rozmiary okna. Musi byc 0 < minWidth <= maxWidth, 0 < minHeight <= Jesli sprobujesz samemu zainicjowac Width lub Height okienka na cos spoza tego zakresu - jesli to bedzie mniejsze od minWidth to zostanie przyjete minWidth, jesli wieksze od maxWidth - zostanie przyjete maxWidth (tzn. zostanie poprawione dopiero w Init !). Bedzie to wykonane nawet jesli ResizeAllowed = raNotAllowed ! Wiec pamietaj ze jesli chcesz zeby ResizeAllowed = raNotAllowed bylo honorowane - width i height musza sie zawierac w min/max Width/Height. Podobnie, jezeli ustawisz Fullscreen := true i okaze sie ze rozmiary ekranu sa zle - flaga FullScreen zostanie wylaczona. Innymi slowy, niniejsze ograniczenia maja priorytet ponad ResizeAllowed, a wszystkie razem (min/maxWidth/Height i ResizeAllowed) maja priorytet nad Width, Height, FullScreen. Tym sposobem ZAWSZE bedzie zachodzic minWidth <= width <= maxWidth, o ile tylko not Closed. I wszystko co napisalem dziala tak samo dla Height. | |
![]() |
AccumBufferBits: TVector4Cardinal; |
|
Required number of bits in color channels of accumulation buffer. Color channel is 0..3: red, green, blue, alpha. Zero means that given channel of accumulation buffer is not needed, so when the vector is all zeros (default value) this means that accumulation buffer is not needed at all. Just like with other XxxBufferBits property, we may get more bits than we requested. But we will never get less — if window system will not be able to provide GL context with requested number of bits, Init will raise an error. | |
![]() |
OnCloseList: TDynGLWindowFuncArray; |
|
podobnie jak OnInit, OnClose tez ma swoja wersje listowa : | |
![]() |
OnKeyDown: TKeyCharFunc; |
|
Not all keyboard keys can be represented as TKey value. There are some keys that generate sensible char values, but still cannot be represented as TKey value, e.g. key '/' does not have any K_Xxx constant for now but can be expressed as char '/'. So you can get Key = K_None is such situations, e.g. Character c is based on pressed key, current Modifiers state, state of keys like "Caps-Lock" , maybe some OS configurarion (like locale-specific chars, e.g. polish "ogonki"), etc. In general, it is operating-system (and window-system, and GLWindow-backend) specific. Not all key presses are representable as char, so you may get c = #0 in such situations. E.g. "up arrow" key does not have a corresponding char code, so Never will both Key = K_None and c = #0 (this would be rather useless event...). (Unless you will explicitely call EventKeyDown(K_None, #0), which you should never do.) Note: once I had here separate events, OnKeyPress (with only c: char) and polish: KeyDown moze byc pod wplywem key repeata. Tzn. ze jesli uzytkownik bedzie trzymal klawisz przycisniety to my mozemy dostawac co chwila nowe KeyDown. Pod niektorymi systemami moze byc wtedy tak ze przed kazdym KeyDown bedziemy dostawali "udawane" KeyUp (udawane, bo user tak naprawde ani na chwile nie puscil klawisza) a pod niektorymi nie bedziemy dostawali KeyUp (bedziemy po prostu dostawali KeyDown(k) podczas gdy juz wczesniej KeysDown[k] = true). Piszac program musisz byc gotow na obie mozliwosci. Podsumowujac : nie patrz na KeyDown(k) jako na "zdarzenie ktore zachodzi gdy KeysDown[k] zmienia sie z false na true". To tak nie dziala. Patrz raczej na to jako na zdarzenie po ktorym KeysDown[k] na pewno jest true. | |
![]() |
OwnsMainMenu: boolean; |
|
If true then in TGLWindow destructor MainMenu will be destroyed too (if not nil, od course). Usually this is something useful. | |
![]() |
OnMenuCommand: TMenuCommandFunc; |
|
Each time user will choose some menu item (let's name it MenuItem), we will call MenuItem.DoCommand. If this will return false then we will call EventMenuCommand (that will call | |
![]() |
UserData: Pointer; |
|
| |
![]() |
KeysDown: TKeysBooleans; |
|
You can check whether some key is pressed using array below. Note that this array is read-only from outside of this class ! Always | |
![]() |
function MakeGLAreaContainer(GLArea: PGtkGLArea): PGtkWidget; virtual; |
|
Implementation of This means that you can override The only requirement is that GLArea widget must be placed somewhere inside widget that you return in this function. Note: if you create here some widgets, remember to show them using gtk_widget_show. Some notes about using this function: Using this function kills some part of portability of GLWindow unit, as this function exists only when GLWindow is implemented on top of GTK, so you will have to always use GLWindow implemented on top GTK on every OS, e.g. with Windows version of your program you will have to distribute GTK and GtkGLExt/GLArea for Windows. This is not really a problem, since GTK 2.x and GtkGLExt work excellent also under Windows (you know, GTK itself is a library that provides great portability). However this raises a question: what are advantages of using in such situation GLWindow unit (as opposed to just using directly Gtk and GtkGLExt API without any need for GLWindow unit): well, my advice is that if your program uses it's OpenGL area as it's central and crucial part (and using some GUI only to e.g. get some input from user about what to display in OpenGL area), than using GLWindow unit may be more straightforward as you have to write much less code in Gtk. Example of using this can be found in ../examples/test_glwindow_gtk_mix | |
![]() |
procedure EventResize; virtual; |
|
EventXxx virtual methods ————————————————- W sekcji private zdefiniowane sa procedury DoXxx ktore wykonuja niezalezna od implementacji GLWindow robote z opakowaniem zdarzen OnXxx. Oto jak to jest robione : najwazniejsza czescia tych procedur jest wywolanie odpowiedniej procedury EventXxx. Procedura EventXxx ma za zadanie z kolei wywolac odpowiednie OnXxx (o ile to jest zdefinoiwane, czyli Assigned(OnXxx)) i ew. OnXxxList jezeli zdarzenie ma swoja wersje listowa, jak OnInit czy OnClose. Wszystkie procedury OnXxx sa wywolywane przez try OnXxx except on BreakGLWinEvent do ; end albo cos rownowaznego. Czyli rzucenie w czasie OnXxx wyjatkiem BreakGLWinEvent spowoduje powrot do aktualnego EventXxx a sam wyjatek zostanie wyciszony (wylapany i zignorowany). W przypadku zdarzen listowych OnXxxList wyjatek zostanie wylapany w obrebie wywolania pojedynczego elementu listy, tzn. BreakGLWinEvent spowoduje przejscie do wykonywania nastepnej na liscie OnXxxList precedury. Pytanie : po co nam ten dodatkowy stopien do zejscia, tzn. procedury EventXxx ? Mianowicie, procedury EventXxx sa wirtualne. W zwiazku z tym pozwalaja one na konstruowanie uzytecznych podklas klasy TGLWindow. Przy okazji procedury te sa nie w protected ale w public aby umozliwic wygodne wywolywanie ich spoza klasy TGLWindow, np. gdy chcesz recznie spowodowac OnResize na jakims window wygodniej jest wywolac glwin.EventResize niz if Assigned(glwin.OnResize) then glwin.OnResize(glwin); albo nawet if Assigned(glwin.OnResize) then try glwin.OnResize(glwin) except on BreakGLWinevent do ; end Pamietaj przy tym ze przed kazdym EventXxx musi byc wywolane MakeCurrent ! (DoXxx robia to automatycznie, podobnie jak pare wewnetrznych rzeczy). | |
![]() |
procedure EventInit; virtual; |
![]() |
procedure EventClose; virtual; |
![]() |
function EventCloseQuery: boolean; virtual; |
|
| |
![]() |
procedure EventDraw; virtual; |
![]() |
procedure EventBeforeDraw; virtual; |
![]() |
procedure EventKeyDown(Key: TKey; c: char); virtual; |
![]() |
procedure EventKeyUp(key: TKey); virtual; |
![]() |
procedure EventMouseMove(newX, newY: integer); virtual; |
![]() |
procedure EventMouseDown(btn: TMouseButton); virtual; |
![]() |
procedure EventMouseUp(btn: TMouseButton); virtual; |
![]() |
procedure EventIdle; virtual; |
|
UWAGA : jezeli pokrywasz | |
![]() |
procedure EventTimer; virtual; |
![]() |
procedure EventMenuCommand(Item: TMenuItem); virtual; |
![]() |
function AllowsProcessMessageSuspend: boolean; virtual; |
|
w glwm.ProcessMessage wykonywana jest bardzo wazna rzecz zaoszczedzajaca cykle procesora : program ktory nie ma zadnego idle ani timer zarejestrowanego ani nie zostalo wywolane glwm.Quit ma prawo "zawisnac" na oczekiwanie message'a od winsystemu. Aby takie cos dzialalo musi byc sposob aby uzyskac od okna informacje czy wykonuje ono cos w EventIdle / EventTimer. (no bo jezeli tak to nie wolno nam robic takiego zawieszania sie). W bazowej klasie TGLWindow EventIdle / EventTimer wywoluja tylko OnIdle / OnTimer, w zwiazku z czym ta funkcja zwraca not (Assigned(OnIdle) or Assigned(OnTimer)) ale to sie moze zmienic jesli pokryjesz EventIdle/ Timer i dorobisz tam jakas funkcjonalnosc. | |
![]() |
procedure SetMousePosition(const NewMouseX, NewMouseY: Integer); |
|
This instructs window manager to place mouse at NewMouseX and NewMouseY position. NewMouseX and NewMouseY are specified just like MouseX and MouseY properties are given, so they are relative to OpenGL area, and 0,0 is upper-top corner. Note that the resulting position may be different than MouseX and MouseY, e.g. if part of the window is offscreen then window manager will probably refuse to move cursor offscreen. This *may* generate normal OnMouseMove event, just as if the user moved the mouse. But it's also allowed to not do this. Use this only when window is not closed. | |
![]() |
procedure Init; |
|
Initialize window (create window with GL context, show window).
Call to Raises EGLContextNotPossible if it's not possible to obtain OpenGL context with specified attributes. For example, maybe you set (Depth|Stencil|Accum)BufferBits properties to too high values. It's guaranteed that even when EGLContextNotPossible was raised, the window remains in correct (Closed) state, so you can try to lower some requirements and call Shadows := true; Glw.StencilBufferBits := 8; try Glw.Init; except on EGLContextNotPossible do begin Shadows := false; Glw.StencilBufferBits := 0; { try to init once again, this time without requesting stencil buffer } Glw.Init; end; end;
Exceptions raised
| |
![]() |
procedure Close(QuitWhenLastWindowClosed: boolean = true); |
|
Note that often there's no need to call TODO: zrobic param boolean CloseFromDestroyQuitWhenLastWindowClosed ? As for now Call to | |
![]() |
procedure PostRedisplay; |
|
Note: if window is Closed then | |
![]() |
procedure FlushRedisplay; |
|
Nie powinienes zbyt czesto potrzebowac tej funkcji. Psuje ona cala optymalizacje wyswietlania ktora stara sie wykonac wyswietlanie jak najpozniej wykonujac najpierw wszystko inne. Generalnie, napisanie kodu w rodzaju begin PostRedisplay; Ale jest jeden wazny moment kiedy naprawde powinienes wywolac ta funkcje : kiedy zamierzasz zrobic zrzut wlasnego ekranu (np. przez glReadPixels). Zalezy ci wtedy zeby ekran przedstawial rzeczywiscie to co powinien - - i nie chcesz byc zalezny od tego czy ostatnie PostRedisplay zdazylo czy tez nie zdazylo sie wywolac. Przed kazdym glReadPixels i generalnie przed innymi operacjami odczytujacymi zawartosc buforow OpenGLa powinienes sie upewnic ze sa one odswiezone wywolujac Pamietaj ze | |
![]() |
procedure MakeCurrent; |
|
Each GLWindow has it's own OpenGL context. Before each window callback the calling window is guaranteed to be the current one - but sometimes you may need to manually set openGL context to a particular window. Note : Init of a window sets this window implicitly to be the current one ! | |
![]() |
procedure SaveScreen(const fname: string); overload; |
|
The intention is to do: FlushRedisplay + KambiGLUtils.SaveScreenXxx_noflush(..,GL_FRONT) However: see comments at KambiGLUtils.SaveScreenXxx_noflush for some warnings about saving from front buffer. In short : you really do not want to save contents of front buffer. So when DoubleBuffer = true, these functions actually do something more reliable: EventDraw + KambiGLUtils.SaveScreenXxx_noflush(..,GL_BACK). (when DoubleBuffer = false no such workaround is possible so just be prepared for some nasty visual effects, as described in comments at KambiGLUtils.SaveScreenXxx_noflush). If you *intent* to use something other than GL_FRONT, or simply have some more advanced needs than just "save current screen", use KambiGLUtils.SaveScreenXxx_noflush instead of these. | |
![]() |
function SaveScreen: TRGBImage; overload; |
![]() |
function SaveScreen( const xpos, ypos, SavedAreaWidth, SavedAreaHeight: integer): TRGBImage; overload; |
![]() |
function SaveScreenToDisplayList: TGLuint; overload; |
![]() |
function SaveScreenToDisplayList(const xpos, ypos, SavedAreaWidth, SavedAreaHeight: integer): TGLuint; overload; |
![]() |
procedure SaveScreenDialog(ProposedFileName: string); |
|
This asks user where to save the file (using FileDialog, as default filename taking ProposedFname), if user accepts calls glwin.SaveScreen(user-chosen-file-name); | |
![]() |
function GetCallbacksState: TGLWindowCallbacks; |
|
Methods for simply saving and restoring value of all OnXxx callbacks (with the exception of OnInit, OnInitList and OnClose, OnCloseList). See also | |
![]() |
procedure SetCallbacksState(const Callbacks: TGLWindowCallbacks); |
![]() |
constructor Create; |
![]() |
destructor Destroy; override; |
![]() |
function ModifiersDown: TModifierKeys; |
|
The same thing as Keys.ModifiersDown(KeysDown). | |
![]() |
function FpsFrameTime: Double; |
|
Fps _ Frame/RealTime: ile razy na sekunde aplikacja generuje ramke. Mierza one czas troche inaczej : RealTime zwraca prawde, tzn. liczy ile ramek na sekunde wyswietla twoja aplikacja. FrameTime robi w pewnym sensie oszustwo : za czas jaki uplynal uznaje czas spedzony tylko na renderowaniu ramek. Tzn. ze jesli FrameTime mowi np. "100 ramek na sek" to znaczy ze gdyby aplikacja spedzala caly czas na generowaniu ramek (tzn. na DrawGL + glFlush / swap buffers robione w ProcessGLWinMessage) to robilaby ich 100 na sekunde. FrameTime nie uwzglednia faktu ze aplikacja moze spedzac duzo czasu takze na innych zajeciach, w OnIdle na przyklad. Przy okazji : widac stad ze na wartosc FramesPerSec duzy wplyw ma to co rzeczywiscie robisz w DrawGL. Wszystko co robisz w DrawGL FrameTime uznaje za "renderowanie ramki". | |
![]() |
function FpsRealTime: Double; |
![]() |
procedure FpsToCaption(const WindowTitle: string); |
|
wypisz ladnie FramesPerSec Frame/Real Time na GLWindow.Caption | |
![]() |
procedure FpsReset; |
|
Aby zresetowac timer mozna wywolac FpsActive(false) i potem (true). Mozna tez uzyc ponizszej procedury | |
![]() |
procedure InitLoop; overload; |
|
———————————————————————— gotowe funkcje ktore realizuja "uproszczony scenariusz", same inicjuja typowe wartosci, wywoluja Init a potem glwm.Loop; | |
![]() |
procedure InitLoop(const ACaption: string; AOnDraw: TDrawFunc); overload; |
![]() |
procedure ParseParameters(); overload; |
|
Parse some parameters from Parameters[1]..Parameters[Parameters.High]. Delete processed parameters from Parameters. Arguments to this proc tell which options are allowed: poGeometry : allowed options are –fullscreen (ustawia Fullscreen := true) –geometry followed by param WIDTHxHEIGHTsXOFFsYOFF gdzie WIDTH, HEIGHT sa liczbami calkowitymi, XOFF, YOFF sa liczbami calkowitymi z opcjonalnym znakiem. (ustawia Fullscreen := false i Width, Height, Left, Top odpowednio - patrz 'man X' po opis co mozna wyrazic parametrem -geometry) poScreenGeometry –fullscreen-custom WIDTHxHEIGHT (ustawia Fullscreen = true, VideoResize := true, VideResizeWidth/Height inicjuje i robi VideoChange) poDisplay –display (set Glwm.XDisplayName) Multiple options of the same kind are allowed, for example two options –fullscreen –geometry 100x100+0+0 are allowed. Each of them will have appropriate effect - in the above example, –fullscreen param will be useless (it will be "overriden" by –geometry param that comes later). This is to allow flexible calling my programs from shell scripts etc. Jezeli parametry sa zle (np. poGeometry in AllowedOptions i zly format parametru za –geometry lub brak parametru za –geometry) -> -> wyjatek EInvalidParams. Wersja 2-argumentowa zwraca jakie grupy parametrow zostaly odczytane i zinterpretowane. Np. jezeli poGeometry in SpecifiedOptions to wiesz ze user podal window size i position i nie powinnismy juz sami tego ustawiac. Chociaz zazwyczaj wystarczy po prostu ustawic w programie Width/Height/Left/Top i potem wywolac ParseParameters i wtedy juz nie trzeba przejmowac sie czy poGeometry bylo czy nie bylo w SpecifiedOptions. | |
![]() |
procedure ParseParameters(const AllowedOptions: TGLWindowParseOptions); overload; |
![]() |
procedure ParseParameters(const AllowedOptions: TGLWindowParseOptions; out SpecifiedOptions: TGLWindowParseOptions); overload; |
![]() |
class function ParseParametersHelp( const AllowedOptions: TGLWindowParseOptions; AddHeader: boolean): string; |
|
Returns help text for options in AllowedOptions. The idea is that if you call Returned string may be multiline, but it does not contain the trailing newline (newline char after the last line). Returned help text conforms my rules in file base/README.kambi_command_line_params If AddHeader then it adds text 'Window options:' +nl at the beginning. This is just a small thing that allows you to comfortably use the output of this function as a whole paragraph (separated from the rest of your "–help" text by e.g. empty lines around). | |
![]() |
function ColorDialog(var Color: TVector3Single): boolean; |
|
Shows a dialog window allowing user to choose an RGB color. Initial value of Color specifies initial RGB values proposed to the user. If user accepts, returns true and sets Color accordingly, else returns false (and does not modify Color). | |
![]() |
property BorderWidth: Cardinal
read FBorderWidth write FBorderWidth default 0; |
|
Change this only when Closed. This is the width of border of main GtkWindow that will be created in Init, set with gtk_container_set_border_width. | |
![]() |
property Width: integer read FWidth write FWidth default GLWindowDefaultSize; |
|
Left, Top, min/maxWidth/Height i ResizeAllowed ustawiaja scisle ograniczenia na Poniewaz WindowManager (WindowManager X-ow lub Windows) moze dosc swobodnie traktowac nasze wymagania min/maxWidth/Height i ResizeAllowed wiec jest niestety mozliwe ze rzeczywiste wymiary okienka beda sie roznic od zadanych w Aplikacje polegajace na tym na poczatku (po zainicjowaniu gl contextu) glViewport jest ustawiony na wymiary okienka moga byc spokojne : wprawdzie rzeczywiste okienko moze nie miec rozmiarow GLWindowDefaultSize will be treated specifically: at Init, will be replaced with some comfortable size slightly smaller than screen size. | |
![]() |
property Height: integer read FHeight write FHeight default GLWindowDefaultSize; |
![]() |
property Left: integer read FLeft write FLeft; |
|
jezeli | |
![]() |
property Top : integer read FTop write FTop; |
![]() |
property FullScreen: boolean read FFullScreen write FFullScreen; |
![]() |
property DoubleBuffer: boolean read FDoubleBuffer write FDoubleBuffer default true; |
|
| |
![]() |
property ColorBits: integer
read FColorBits write FColorBits default 0; |
|
Warning: this symbol is deprecated.
TODO: uzywanie tej wlasciwosci jest deprecated. Jest ona non-cross-platform, interfejs nie czyni zadnych gwarancji ze rzeczywiscie dostaniemy wymagane | |
![]() |
property Cursor: TGLWindowCursor read FCursor write SetCursor default gcDefault; |
|
Sets mouse TODO: for now, gcCustom is not handled anywhere. | |
![]() |
property CustomCursor: TAlphaImage read FCustomCursor
write SetCustomCursor; |
|
Image for cursor, used only when Cursor = gcCustom. We will try hard to use any cursor image as appropriate, but on some platforms cursor size may be limited (16 x 16 seems standard for GTK) and cursor may be forced to monochrome. Note that you still own the TAlphaImage instance passed here — you're responsible for freeing it etc. If this is TODO: for now, this is not implemented. Cursor ignores gcCustom value, under every GLWindow implementation... sorry, CustomCursor is only a plan. | |
![]() |
property ResizeAllowed: TResizeAllowed read FResizeAllowed write FResizeAllowed; |
|
Naklada ograniczenia na to kiedy i jak Width i Height moga sie zmienic. = raNotAllowed oznacza ze Width i Height nie moga sie zmienic CHYBA ze po to zeby dostosowac sie do min/maxWidth/Height. Tak ostre ograniczenia moga nawet spowodowac ze przy probie Init okienka z atrybutem Fullscreen = true flaga Fullscreen moze zostac wylaczone na true. Ale masz PEWNOSC ze Width i Height zawsze beda rowne zadanym, o ile tylko beda w granicach min/maxWidth/Height. = raOnlyAtInit oznacza ze rozmiary okienka moga zostac zainicjowane na inne niz podane jezeli np. WindowManager ma obiekcje co do zadanych przez nas rozmiarow okienka albo jezeli chcesz miac Fullscreen i ScreenWidth/H sa rozne od Width/Height. W tych przypadkach, i byc moze takze w innych podobnych rozmiary Width/Height jakie dostanie okienko beda rozne od zadanych Width/Height. Ale masz PEWNOSC ze po wywolaniu pierwszego callbacka (czyli EventInit (OnInit), tuz przed pierwszym EventResize (OnResize)) Width/Height juz beda stale, dopoki okienko bedzie not Closed. = raAllowed jest domyslne i pozwala na najwieksza swobode WindowManagerowi i userowi : okienko moze byc zresizowane w dowolnym momencie. Oznacza to ze nie tylko Width/Height jakie dostaniesz w pierwszych OnInit i OnResize moga byc inne niz te ktorych zazadales ale takze w trakcie dzialania programu rozmiary okienka moga sie zmieniac. Powinienes byc na to przygotowany obslugujac zdarzenie OnResize (ktore w zasadzie jest zupelnie zbedne w pozostalych przypadkach, gdy | |
![]() |
property OnInit: TGLWindowFunc read FOnInit write FOnInit; |
|
Jest GWARANTOWANE ze dla kazdego nowootwartego okna NAJPIERW zostanie wyslany EventInit ( This is a sensible and consequential approach – EventInit ( One more thing: in EventInit ( | |
![]() |
property DepthBufferBits: Cardinal
read FDepthBufferBits write FDepthBufferBits default DefaultDepthBufferBits; |
|
Required depth buffer precision. Zero means that we don't need depth buffer at all. We may get depth buffer with more precision than requested (we may even get depth buffer when we set Default value is 16 (DefaultDepthBufferBits), which is a reasonable default for 3D programs that want to work with depth test enabled. Design notes: One may ask why default value is not 0 ?
Of course, if you are writing a program that does not need depth buffer you should set glw.DepthBufferBits := 0. The only advantage of having default | |
![]() |
property StencilBufferBits: Cardinal
read FStencilBufferBits write FStencilBufferBits default 0; |
|
Required stencil buffer precision, zero means that stencil buffer is not needed. Just like with other XxxBufferBits property, we may get more bits than we requested. But we will never get less — if window system will not be able to provide GL context with requested number of bits, Init will raise an error. | |
![]() |
property MultiSampling: Cardinal
read FMultiSampling write FMultiSampling default 1; |
|
How many samples are required for So the only thing remaining for your program to make anti-aliasing working is to use core OpenGL extension GL_ARB_multisample: [http://opengl.org/registry/specs/ARB/multisample.txt]. In the usual case, this means simply to call if GL_ARB_multisample then glEnable(GL_MULTISAMPLE_ARB);
and if GL_ARB_multisample then glDisable(GL_MULTISAMPLE_ARB);
Just like with other XxxBufferBits property, we may get more samples than we requested (e.g. if you request 3, you will most probably get 4...). But we will never get less — if window system will not be able to provide GL context with requested number of bits, Init will raise an error. | |
![]() |
property AlphaBits: Cardinal
read FAlphaBits write FAlphaBits default 0; |
|
Required number of bits in alpha channel of color buffer. Zero means that alpha channel is not needed. Just like with other XxxBufferBits property, we may get more bits than we requested. But we will never get less — if window system will not be able to provide GL context with requested number of bits, Init will raise an error. It's undefined how I'll treat this variable when indexed color mode will be possible in TGLWindow. | |
![]() |
property Caption: string read FCaption write SetCaption; |
|
———————————————————————– rzeczy ktore mozesz inicjowac przed wywolaniem Init ale mozesz tez nimi swobodnie manipulowac pozniej. | |
![]() |
property OnDraw: TDrawFunc read FOnDraw write FOnDraw; |
|
This is probably the most important callback. You should redraw your window here. It will be called when your window contents must be redrawn, e.g. after creating a window, after resizing a window, after uncovering the window etc. You can also request that this callback should be called in a short time by PostRedisplay. Note: calling PostRedisplay while in EventDraw ( | |
![]() |
property OnBeforeDraw: TDrawFunc read FOnBeforeDraw write FOnBeforeDraw; |
|
Only one thing differs OnDraw and E.g. view3dscene uses Scene.Render. From time to time user presses a key like "g" or "m" that force the whole Scene to be regenerated. This means that a call to Scene.Render inside OnDraw takes sometimes much more time than it usually does. This gives some unpleasant effect because when the user views the scene using "Examine" mode then after pressing "g" FpsCompSpeed is (for only one short moment !) very big. And this means that after pressing "g" user sees 1. first, it takes some time to regenerate the model 2. second, after regenerating the model there is a sudden jump in the amount the object is rotated (because FpsCompSpeed is big). And the second thing is bad. It can avoided by putting Scene.PrepareRender(true) after OnKeyDown, OnMouseDown etc. But the simplest (and more elegant) way is to put Scene.PrepareRender(true) only in | |
![]() |
property OnResize: TGLWindowFunc read FOnResize write FOnResize; |
|
Kiedys bylo automatyczne glViewport przed I jeszcze jest gwarantowane ze zdarzenie 2D OpenGL programs may want to register here simple Resize2D. | |
![]() |
property OnClose: TGLWindowFunc read FOnClose write FOnClose; |
|
jesli assigned, to bedzie wywolywane | |
![]() |
property OnKeyUp: TKeyFunc read FOnKeyUp write FOnKeyUp; |
|
Key is never K_None. Note: I had at some time an idea to add "c: char" parameter to | |