Class TCastleWindowBase

DescriptionHierarchyFieldsMethodsProperties

Unit

Declaration

type TCastleWindowBase = class(TComponent)

Description

Window with an OpenGL context. See CastleWindow unit description for more info and examples of use.

Hierarchy

  • TComponent
  • TCastleWindowBase

Overview

Fields

Public AccumBits: TVector4Cardinal;

Methods

Public procedure EventResize; virtual;
Public procedure EventOpen; virtual;
Public procedure EventClose; virtual;
Public function EventCloseQuery: boolean; virtual;
Public procedure EventDraw; virtual;
Public procedure EventBeforeDraw; virtual;
Public procedure EventPress(const Event: TInputPressRelease); virtual;
Public procedure EventRelease(const Event: TInputPressRelease); virtual;
Public procedure EventMouseMove(newX, newY: integer); virtual;
Public procedure EventIdle; virtual;
Public procedure EventTimer; virtual;
Public procedure EventMenuCommand(Item: TMenuItem); virtual;
Public function AllowSuspendForInput: boolean; virtual;
Public procedure SetMousePosition(const NewMouseX, NewMouseY: Integer);
Public procedure Open;
Public procedure Open(const Retry: TGLContextRetryOpenFunc);
Public procedure Close(QuitWhenLastWindowClosed: boolean = true);
Public procedure PostRedisplay;
Public procedure FlushRedisplay;
Public procedure MakeCurrent;
Public procedure SaveScreen(const fname: string); overload;
Public function SaveScreen: TRGBImage; overload;
Public function SaveAlignedScreen: TRGBImage;
Public function SaveScreenToGL: TGLImage; overload;
Public function SaveScreen( const xpos, ypos, SavedAreaWidth, SavedAreaHeight: integer): TRGBImage; overload;
Public function SaveScreenToGL( const xpos, ypos, SavedAreaWidth, SavedAreaHeight: integer): TGLImage; overload;
Public procedure SaveScreenDialog(ProposedFileName: string);
Public constructor Create(AOwner: TComponent); override;
Public destructor Destroy; override;
Public procedure FpsToCaption(const WindowTitle: string);
Public procedure OpenAndRun; overload;
Public procedure OpenAndRun(const ACaption: string; AOnDraw: TDrawFunc); overload;
Public procedure ParseParameters( const AllowedOptions: TWindowParseOptions = StandardParseOptions); overload;
Public procedure ParseParameters( const AllowedOptions: TWindowParseOptions; out SpecifiedOptions: TWindowParseOptions); overload;
Public class function ParseParametersHelp( const AllowedOptions: TWindowParseOptions; AddHeader: boolean): string;
Public function FileDialog(const Title: string; var FileName: string; OpenDialog: boolean; FileFilters: TFileFilterList = nil): boolean; overload;
Public function FileDialog(const Title: string; var FileName: string; OpenDialog: boolean; const FileFilters: string): boolean; overload;
Public function ColorDialog(var Color: TVector3Single): boolean;
Public function ColorDialog(var Color: TVector3Byte): boolean;
Public procedure MessageOK(const S: string; const MessageType: TWindowMessageType);
Public function MessageYesNo(const S: string; const MessageType: TWindowMessageType = mtQuestion): boolean;

Properties

Public property BorderWidth: Cardinal read FBorderWidth write FBorderWidth default 0;
Public property Width: integer read FWidth write FWidth default WindowDefaultSize;
Public property Height: integer read FHeight write FHeight default WindowDefaultSize;
Public property Left: integer read FLeft write FLeft default WindowPositionCenter;
Public property Top : integer read FTop write FTop default WindowPositionCenter;
Public property FullScreen: boolean read FFullScreen write FFullScreen default false;
Public property DoubleBuffer: boolean read FDoubleBuffer write FDoubleBuffer default true;
Public property RedBits: Cardinal read FRedBits write FRedBits default 0;
Public property GreenBits: Cardinal read FGreenBits write FGreenBits default 0;
Public property BlueBits: Cardinal read FBlueBits write FBlueBits default 0;
Public property ColorBits: Cardinal read GetColorBits write SetColorBits stored false default 0;
Public property Cursor: TMouseCursor read FCursor write SetCursor default mcDefault;
Public property CustomCursor: TRGBAlphaImage read FCustomCursor write SetCustomCursor;
Public property ResizeAllowed: TResizeAllowed read FResizeAllowed write FResizeAllowed default raAllowed;
Public property OnOpen: TWindowFunc read FOnOpen write FOnOpen;
Public property MinWidth: Integer read FMinWidth write FMinWidth default 100;
Public property MinHeight: Integer read FMinHeight write FMinHeight default 100;
Public property MaxWidth: Integer read FMaxWidth write FMaxWidth default 4000;
Public property MaxHeight: Integer read FMaxHeight write FMaxHeight default 4000;
Public property DepthBits: Cardinal read FDepthBits write FDepthBits default DefaultDepthBits;
Public property StencilBits: Cardinal read FStencilBits write FStencilBits default 0;
Public property MultiSampling: Cardinal read FMultiSampling write FMultiSampling default 1;
Public property AntiAliasing: TAntiAliasing read FAntiAliasing write SetAntiAliasing default DefaultAntiAliasing;
Public property AlphaBits: Cardinal read FAlphaBits write FAlphaBits default 0;
Public property GtkIconName: string read FGtkIconName write FGtkIconName;
Public property Visible: boolean read FVisible write FVisible default true;
Public property Caption: string read FCaption write SetCaption;
Public property OnDraw: TDrawFunc read FOnDraw write FOnDraw;
Public property OnBeforeDraw: TDrawFunc read FOnBeforeDraw write FOnBeforeDraw;
Public property OnResize: TWindowFunc read FOnResize write FOnResize;
Public property OnClose: TWindowFunc read FOnClose write FOnClose;
Public property OnPress: TInputPressReleaseFunc read FOnPress write FOnPress;
Public property OnRelease: TInputPressReleaseFunc read FOnRelease write FOnRelease;
Public property OnCloseQuery: TWindowFunc read FOnCloseQuery write FOnCloseQuery;
Public property OnMouseMove : TMouseMoveFunc read FMouseMove write FMouseMove;
Public property OnIdle: TWindowFunc read FOnIdle write FOnIdle;
Public property OnTimer: TWindowFunc read FOnTimer write FOnTimer;
Public property AutoRedisplay: boolean read fAutoRedisplay write SetAutoRedisplay;
Public property MainMenu: TMenu read FMainMenu write SetMainMenu;
Public property OwnsMainMenu: boolean read FOwnsMainMenu write FOwnsMainMenu default true;
Public property OnMenuCommand: TMenuCommandFunc read FOnMenuCommand write FOnMenuCommand;
Public property MousePressed: TMouseButtons read FMousePressed;
Public property MouseX: integer read FMouseX;
Public property MouseY: integer read FMouseY;
Public property UserData: Pointer read FUserData write FUserData;
Public property Closed: boolean read FClosed default true;
Public property Pressed: TKeysPressed read FPressed;
Public property Fps: TFramesPerSecond read FFps;

Description

Fields

Public AccumBits: 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 XxxBits 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, Open will raise an error.

Methods

Public procedure EventResize; virtual;

Handle appropriate event.

In the TCastleWindowBase class, these methods simply call appropriate OnXxx callbacks (if assigned). Also CastleUIControls.OnGLContextOpen, CastleUIControls.OnGLContextClose lists are called here too.

You can override them to do anything you want.

You can also call these methods directly for some tricks. You may want to do MakeCurrent before calling them directly, if your application may have many OpenGL windows. When EventXxx are called internally from this unit, they are always preceded by MakeCurrent call.

Notes for overriding OnIdle and OnTimer: you will usually also want to override then AllowSuspendForInput, to disallow suspending when you want to keep receiving idle/timer calls.

Notes for overriding OnCloseQuery: you have to return True to allow closing of the window.

Public procedure EventOpen; virtual;
 
Public procedure EventClose; virtual;
 
Public function EventCloseQuery: boolean; virtual;
 
Public procedure EventDraw; virtual;
 
Public procedure EventBeforeDraw; virtual;
 
Public procedure EventPress(const Event: TInputPressRelease); virtual;
 
Public procedure EventRelease(const Event: TInputPressRelease); virtual;
 
Public procedure EventMouseMove(newX, newY: integer); virtual;
 
Public procedure EventIdle; virtual;
 
Public procedure EventTimer; virtual;
 
Public procedure EventMenuCommand(Item: TMenuItem); virtual;
 
Public function AllowSuspendForInput: boolean; virtual;

Is it allowed to suspend (for an indefinite amount of time) waiting for user input.

Allowing this is a good thing, as it means our process doesn't eat your CPU when it simply waits, doing nothing, for user input. On the other hand, you cannot allow this if you want to do some things continously, regardless of user input.

In this class, this simply checks if OnIdle or OnTimer events are assigned. If one of them is, we do not allow to suspend. In descendants, you typically want to override this if there's a chance you may do something in overridden EventIdle or EventTimer.

Public procedure SetMousePosition(const NewMouseX, NewMouseY: Integer);

Place mouse cursor at NewMouseX and NewMouseY. Position is specified relative to this window's upper-top corner (more specifically, OpenGL area upper-top corner), just like MouseX and MouseY properties.

Note that the actually set position may be different than requested, for example if part of the window is offscreen then window manager will probably refuse to move mouse 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.

Ignored when window is closed.

Public procedure Open;

Create the window with associated OpenGL context and show it.

Call to this method is ignored if the window is already open (if Closed = False).

Exceptions raised
EGLContextNotPossible
If it's not possible to obtain OpenGL context with specified attributes. For example, maybe you set AlphaBits, DepthBits, StencilBits, AccumBits properties too high?

It's guaranteed that when EGLContextNotPossible is raised, the window remains in correct (closed) state. This means that you can catch EGLContextNotPossible and lower some OpenGL buffer requirements and try to open once again. Although it's usually more comfortable to use the overloaded version of Open with Retry callback for this purpose.

This parameterless version of Open automatically turns off multi-sampling (AntiAliasing and MultiSampling properties), and then we turn off stencil buffer (StencilBits), if OpenGL context cannot be initialized. But if it still cannot be initialized, we raise EGLContextNotPossible. You can use overloaded Open version with Retry callback to customize this fallback mechanism, to code which OpenGL context features may be turned off.

Public procedure Open(const Retry: TGLContextRetryOpenFunc);

Open the window with OpenGL context, allowing you to lower the OpenGL context requirements and retry.

If the OpenGL context cannot be initialized, then Retry callback is called. Inside this callback you should either:

  • lower some context requirements (like set MultiSampling to 1 if it was > 1) if possible, and return True to retry, or

  • do not change context requirements and return False to give up.

Note that the parameterless version of Open method actually calls this version, with a default retry callback that turns off AntiAliasing and MultiSampling, and then StencilBits (since all our engine code should be ready that multi-sampling or stencil buffers may not be available). Using your own Retry callback, with this version, allows you to decide which context parameters may be lowered to allow creating a window.

Exceptions raised
EGLContextNotPossible
If it's not possible to obtain requested OpenGL context, and the Retry callback returned False.
Public procedure Close(QuitWhenLastWindowClosed: boolean = true);

Close window.

  • Calls EventClose (and OnClose).

  • Hides window, destroys it.

  • if this was the only open TCastleWindowBase window and QuitWhenLastWindowClosed = true then this calls Application.Quit.

Note that often there's no need to call Close explicitly in your program, because in destructor of this object we call Close, to be sure that window is closed.

TODO: zrobic param boolean CloseFromDestroyQuitWhenLastWindowClosed? As for now Close from destructor is called always with QuitWhenLastWindowClosed = true.

Call to Close is ignored if window is already Closed.

Public procedure PostRedisplay;

Make contents of OpenGL area of this window redrawn, at the nearest good time. The redraw will not happen immediately, we will only "make a note" that we should do it soon. Redraw means that we call EventBeforeDraw (OnBeforeDraw), EventDraw (OnDraw), then we flush OpenGL commands, swap buffers etc.

Calling this on a closed window is allowed and ignored.

Public procedure FlushRedisplay;

Force redraw of OpenGL area right now, only if any redraw is needed.

If we know we should redraw a window (for example, because window manager just said that window is brought to front of the desktop, or because you called PostRedisplay) then we will redraw the window right now. This method will directly call EventBeforeDraw (OnBeforeDraw), EventDraw (OnDraw), flush OpenGL commands, swap buffers and such.

You really should not use this method too often. It's best to leave to this unit's internals decision when the redraw should happen, and allow us to redraw only once even if you called PostRedisplay many times in a short time.

The one valid reason for using this function is when you need to read back the drawn window contents (e.g. by glReadPixels). Then you want to make sure first that any pending redraws are actually done — this method allows you to do this.

Public procedure MakeCurrent;

Make the OpenGL context of this window "current" (following OpenGL commands will apply to this). When the window is opened, and right before calling any window callback, we always automatically call this, so you should not need to call this method yourself in normal circumstances.

Public procedure SaveScreen(const fname: string); overload;

Capture the current window contents to an image (file).

These functions take care of flushing any pending redraw operations (like FlushRedisplay) and capturing the screen contents correctly.

  • When we use OpenGL double buffer, we do something like

      EventBeforeDraw;
      EventDraw;
      CastleGLUtils.SaveScreenXxx_NoFlush(..,GL_BACK);
    

    This draws to the back buffer and captures it's contents, which is reliable.

  • When we do not use OpenGL double buffer, we do something like

      FlushRedisplay;
      CastleGLUtils.SaveScreenXxx_NoFlush(..,GL_FRONT);
    

    This isn't absolutely reliable. Read CastleGLUtils.SaveScreenXxx_NoFlush docs, and OpenGL FAQ: capturing the front buffer contents is generally not reliable with OpenGL.

Public function SaveScreen: TRGBImage; overload;
 
Public function SaveAlignedScreen: TRGBImage;

Saves screen, making sure Image width is a multiple of 4 on buggy Radeon drivers. The meaningful image width is equal to window's Width.

Public function SaveScreenToGL: TGLImage; overload;
 
Public function SaveScreen( const xpos, ypos, SavedAreaWidth, SavedAreaHeight: integer): TRGBImage; overload;
 
Public function SaveScreenToGL( const xpos, ypos, SavedAreaWidth, SavedAreaHeight: integer): TGLImage; overload;
 
Public procedure SaveScreenDialog(ProposedFileName: string);

Asks and saves current screenshot. Asks user where to save the file (using FileDialog, as default filename taking ProposedFname). If user accepts calls Window.SaveScreen. In case of problems with saving, shows a dialog (doesn't raise exception).

Public constructor Create(AOwner: TComponent); override;
 
Public destructor Destroy; override;
 
Public procedure FpsToCaption(const WindowTitle: string);

Set Caption to WindowTitle with description of Fps.FrameTime and Fps.RealTime.

Public procedure OpenAndRun; overload;

Shortcut for Open (create and show the window with GL contex) and Application.Run (run the event loop).

Public procedure OpenAndRun(const ACaption: string; AOnDraw: TDrawFunc); overload;

Shortcut for setting Caption, OnDraw, then calling Open (create and show the window with GL contex) and Application.Run (run the event loop).

Public procedure ParseParameters( const AllowedOptions: TWindowParseOptions = StandardParseOptions); overload;

Parse some command-line options and remove them from Parameters list. AllowedOptions specify which command-line options are handled. See [http://castle-engine.sourceforge.net/opengl_options.php] for documentaion what these options actually do from user's point of view.

poGeometry

Handle these command-line options:

  • --fullscreen: sets FullScreen to True.

  • --geometry: sets FullScreen to False and changes Width, Height, Left, Top as user wants.

poScreenGeometry

Handle --fullscreen-custom: sets FullScreen and VideoResize to True, initializes VideResizeWidth and VideResizeHeight and actually tries to change your desktop resolution by VideoChange.

poDisplay

Handle --display: sets Application.XDisplayName under Unix.

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 overridden by following --geometry param. Such overridding is sometimes useful from shell scripts.

Overloaded version with SpecifiedOptions says which command-line options were found and handled. For example, if poGeometry, then you know that user requested some window size.

Exceptions raised
EInvalidParams
When some of our options have invalid arguments.
Public procedure ParseParameters( const AllowedOptions: TWindowParseOptions; out SpecifiedOptions: TWindowParseOptions); overload;
 
Public class function ParseParametersHelp( const AllowedOptions: TWindowParseOptions; AddHeader: boolean): string;

Help text for options in AllowedOptions. The idea is that if you call ParseParameters(AllowedOptions) in your program then you should also show your users somwhere (e.g. in response to "–help" option) the list of allowed options obtained by ParseParametersHelp(AllowedOptions) (i.e. with the same value of AllowedOptions).

Returned string may be multiline, but it does not contain the trailing newline (newline char after the last line).

Returned help text conforms to rules in castle_game_engine/doc/various/kambi_command_line_params.txt.

If AddHeader then it adds line saying 'Window options:' (and showing backend name, for debug purposes) at the beginning. This 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).

Public function FileDialog(const Title: string; var FileName: string; OpenDialog: boolean; FileFilters: TFileFilterList = nil): boolean; overload;

Select a file to open or save.

This dialog may also allow user for some typical file-management operations by the way (create some directories, rename some files etc.).

Returns True and sets FileName accordingly if user chooses some filename and accepts it. Returns False if user cancels.

Parameters
Title
A dialog title.
FileName
Specifies default filename (path and/or name, or '' if current dir is the default dir and there is no default filename). Note that if you have to specify only path in FileName you have to end this paths with PathDelim (otherwise '/tmp/blah' would not be clear: whether it's filename 'blah' in '/tmp/' dir or whether it's only dir '/tmp/blah/'?).
OpenDialog
Is this an open (True) or save (False) file dialog.

If OpenDialog: force the user to only choose existing (and readable) file. The intention is that you should be able to open FileName for at least reading. We may be unable to force this (especially the "readable" requirement), so you still should watch for some exceptions when opening a file (as is always the case when opening files, anyway).

If not OpenDialog: allows user to select a non-existent filename. Still, it may try to force ExtractFilePath(FileName) to be valid, i.e. user may be forced to choose only filenames with existing paths. (But, again, no guarantees.) Some warning to user may be shown if FileName already exists, like "are you sure you want to overwrite this file?". The intention is that you should be able to open FileName for writing.

FileFilters
A set of file filters to present to user. Pass Nil (default) if you do not want to use file file filters, so user will just always see everything. An overloaded version allows you to pass file filters encoded in a single string, this may be slightly more comfortable for call, see TFileFilterList.AddFiltersFromString for explanation how to encode filters in a string.
Public function FileDialog(const Title: string; var FileName: string; OpenDialog: boolean; const FileFilters: string): boolean; overload;
 
Public 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).

Public function ColorDialog(var Color: TVector3Byte): boolean;
 
Public procedure MessageOK(const S: string; const MessageType: TWindowMessageType);

Simple "OK" dialog box.

Public function MessageYesNo(const S: string; const MessageType: TWindowMessageType = mtQuestion): boolean;

Simple yes/no question dialog box.

Properties

Public 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 Open, set with gtk_container_set_border_width.

Public property Width: integer read FWidth write FWidth default WindowDefaultSize;

Size of the window OpenGL area. Together with frame and border sizes, and eventually menu bar size, this determines the final window size.

MinWidth / MaxWidth / MinHeight / MaxHeight place constraints on these values (rigorously honored when window is open): always MinWidth <= Width <= MaxWidth and MinHeight <= Height <= MaxHeight.

ResizeAllowed places constrains when window manager and user may change window size. In particular, when ResizeAllowed <> raAllowed then window sizes cannot change when window is open.

Note that for some window managers, we cannot always reliably force the size constraints and block resizing on the desktop. If you set rigorous size constraints, or ResizeAllowed <> raAllowed, you may find that window manager still resizes the window. In such cases, we may fake our size a little — Width and Height values may not correspond to actual size as seen on the desktop. This is comfortable, as in such cases you usually want to just ignore window managers limits and just proceed as if your size requirements are satisfied.

Special WindowDefaultSize value of these properties means: at Open, use some comfortable size slightly smaller than desktop size.

Public property Height: integer read FHeight write FHeight default WindowDefaultSize;
 
Public property Left: integer read FLeft write FLeft default WindowPositionCenter;

Window position on the screen. If one (or both) of them is equal to WindowPositionCenter at the initialization (Open) time, then it will be set to position the window at the screen center.

Public property Top : integer read FTop write FTop default WindowPositionCenter;
 
Public property FullScreen: boolean read FFullScreen write FFullScreen default false;
 
Public property DoubleBuffer: boolean read FDoubleBuffer write FDoubleBuffer default true;

Should we request and use the double buffer. After every draw, we automatically swap buffers (if DoubleBuffer) or call glFlush (if not DoubleBuffer).

Public property RedBits: Cardinal read FRedBits write FRedBits default 0;

Required red / green / blue color buffer precision for this window. When 0, the default window system color precision will be used.

You can either set them by separate red / green / blue properties. Or you can use ColorBits that reads / writes all three channels bits. Reading ColorBits simply returns the sum of RedBits + GreenBits + BlueBits. Writing ColorBits simply set RedBits and BlueBits to ColorBits div 3, and sets GreenBits to the remainder. This way green channel has always the best resolution (as is usual, since it's perceived most), and the sum is always as requested. This way setting ColorBits to values like 16 or 24 works as expected.

Note that it's also possible to change color resolution by changing the whole screen settings. See TGLApplication.VideoColorBits and TGLApplication.VideoChange for this. These properties only request the color resolution for this window, which is less intrusive (you don't change the whole screen) but also may have a smaller chance of success.

Public property GreenBits: Cardinal read FGreenBits write FGreenBits default 0;
 
Public property BlueBits: Cardinal read FBlueBits write FBlueBits default 0;
 
Public property ColorBits: Cardinal read GetColorBits write SetColorBits stored false default 0;
 
Public property Cursor: TMouseCursor read FCursor write SetCursor default mcDefault;

Sets mouse cursor appearance over this window. See TMouseCursor for a list of possible values and their meanings.

TODO: for now, mcCustom is not handled anywhere.

Public property CustomCursor: TRGBAlphaImage read FCustomCursor write SetCustomCursor;

Image for cursor, used only when Cursor = mcCustom. 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 TRGBAlphaImage instance passed here — you're responsible for freeing it etc. If this is Nil, and Cursor = mcCustom, then it will be treated like Cursor = mcDefault. (I don't raise error in such case, as that would make changing both Cursor and CustomCursor values unnecessarily tricky for the programmer.)

TODO: for now, this is not implemented. Cursor ignores mcCustom value, under every CastleWindow backend... sorry, CustomCursor is only a plan.

Public property ResizeAllowed: TResizeAllowed read FResizeAllowed write FResizeAllowed default raAllowed;

When (if at all) window size may be changed.

  • raNotAllowed

    Width and Height can only change to honor MinWidth / MaxWidth / MinHeight / MaxHeight constraints. Absolutely nothing else may cause them to change, user cannot resize the window.

    This may even force FullScreen change from True to False at Open call, when you will request a fullscreen window but Width / Height will not match screen size.

    You can be sure that EventResize (OnResize) will be called only once, when window is opened (right after initial EventOpen (OnOpen)).

  • raOnlyAtOpen

    Width and Height may be adjusted when the window is opened, by Open call. For example window manager may decide that the size is too large for the current screen. Or when you request FullScreen window and window size has to be adjusted to match current screen size. Also they will always be adjusted to fit in MinWidth / MaxWidth / MinHeight / MaxHeight constraints.

    After opening, window size cannot change anymore. In particular user cannot resize the window (by dragging border or such). After the first EventOpen (OnOpen) call, the window size becomes constant. From the first EventResize (OnResize) the window size is constant, as long as the window remains open.

    You can be sure that EventResize (OnResize) will be called only once, when window is opened (right after initial EventOpen (OnOpen)).

  • raAllowed

    Width and Height may be adjusted at open time, and later user can resize the window too. This is the default value, giving user and window manager the most flexibility.

    You have to be prepared for this, handling OnResize and adjusting stuff like OpenGL viewport and projection matrix.

Note that the we call the first glViewport automatically in Open. So in typical cases, you don't have to call glViewport ever yourself, when ResizeAllowed <> raAllowed.

Public property OnOpen: TWindowFunc read FOnOpen write FOnOpen;

Event called when OpenGL context is initialized.

It's guaranteed that every newly opened window will get EventOpen (OnOpen) first, and then EventResize (OnResize), and only then — the other callbacks, as the user uses the window. This is consistent EventOpen (OnOpen) is always the first executed callback and EventClose (OnClose) is always the last. This allows you to cleanly initialize / finalize OpenGL resources.

During EventOpen (OnOpen) you already have valid Width / Height values, that is those values were already adjusted if ResizeAllowed <> raNotAllowed.

Public property MinWidth: Integer read FMinWidth write FMinWidth default 100;

Minimum and maximum window sizes. Always

  0 < MinWidth <= MaxWidth and
  0 < MinHeight <= MaxHeight

We do not allow user to resize the window outside of these constraints.

We also fix window Width and Height to fit within these constraints when you Open the window. We do it regardless of ResizeAllowed (even when it's raNotAllowed).

In other words, these constraints have a higher priority than ResizeAllowed and your desired Width and Height and even FullScreen. So you can be sure that (as long as window is open) Width / Height will always fit in these constraints.

Public property MinHeight: Integer read FMinHeight write FMinHeight default 100;
 
Public property MaxWidth: Integer read FMaxWidth write FMaxWidth default 4000;
 
Public property MaxHeight: Integer read FMaxHeight write FMaxHeight default 4000;
 
Public property DepthBits: Cardinal read FDepthBits write FDepthBits default DefaultDepthBits;

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 DepthBits = 0), this all depends on graphic card.

Default value is 16 (DefaultDepthBits), 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?

  1. Most programs using OpenGL use depth testing, so many programs would have to call something like Window.DepthBits := 16.

  2. Often graphic cards / window systems / OSes give you an OpenGL context with depth buffer even if you don't need depth buffer. I don't say that it's bad. But it makes very easy to forget about doing DepthBits := something-non-zero;. If you're writing 3d program and sitting on some system that always gives you depth buffer (even if DepthBits = 0) then it may happen that you forget to write in your program

      Window.DepthBits := 16;

    And while on your system everything will work, you will receive errors on other systems because you forgot to request a depth buffer.

Of course, if you are writing a program that does not need depth buffer you should set Window.DepthBits := 0. The only advantage of having default DepthBits = 16 is that if you forget to set Window.DepthBits := 0 your programs will still work (most graphic cards will give you some depth buffer anyway). They will just use more resources than they should.

Public property StencilBits: Cardinal read FStencilBits write FStencilBits default 0;

Required stencil buffer precision, zero means that stencil buffer is not needed.

Just like with other XxxBits 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, Open will raise an error.

Note that after initializing OpenGL context (when opening the window), StencilBits is not updated to the current (provided) stencil buffer bit size. For example, if you requested StencilBits := 8, and you got 16-bits buffer: StencilBits value will still remain 8. This is sensible in case you close the window, tweak some settings and try to open it again. Use glGetInteger(GL_STENCIL_BITS) when window is open to query current (actual) buffer size.

Public property MultiSampling: Cardinal read FMultiSampling write FMultiSampling default 1;

How many samples are required for multi-sampling (anti-aliasing). Use AntiAliasing instead of this for more comfortable (higher-level) way to turn on multi-sampling (anti-aliasing).

1 means that no multi-sampling is required. Values larger than 1 mean that we require OpenGL context with multi-sampling capabilities. Various GPUs may support various values (it's a trade-off between quality and speed), try typical values 2 or 4.

You can enable/disable anti-aliasing in your program by code like

        if GL_ARB_multisample then glEnable(GL_MULTISAMPLE_ARB);
        if GL_ARB_multisample then glDisable(GL_MULTISAMPLE_ARB);
      

But usually that's not needed, as it is "on" by default (GL_ARB_multisample spec says so) if you requested multi-sampling context (that is, if this property is > 1). See GL_ARB_multisample spec for details: [http://opengl.org/registry/specs/ARB/multisample.txt].

Just like with other XxxBits 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, Open will raise an error. TODO: actually, this may change to be similar to Lazarus TOpenGLControl.MultiSampling, and also be more comfortable — to retry initialization with no multi-sampling. In this case this property will not be changed, to be nice.

You can always read OpenGL GL_SAMPLE_BUFFERS_ARB and GL_SAMPLES_ARB values after initializing OpenGL context, to know exactly how many samples did you actually get, and did you get multi-sampling at all. Actually, we already initialize global CastleGLUtils.GLCurrentMultiSampling for you, you can use this.

Public property AntiAliasing: TAntiAliasing read FAntiAliasing write SetAntiAliasing default DefaultAntiAliasing;

Comfortably turn on/off anti-aliasing.

Setting this property automatically sets also the MultiSampling property. Although it's easy to request multi-sampling by using the MultiSampling property directly, using AntiAliasing is a little more comfortable. You don't have to wonder what are the sensible values of MultiSampling for common GPUs, and we also automatically use NV_multisample_filter_hint for nicer anti-aliasing when possible.

Public 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 XxxBits 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, Open will raise an error.

It's undefined how I'll treat this variable when indexed color mode will be possible in TCastleWindowBase.

Public property GtkIconName: string read FGtkIconName write FGtkIconName;

Name of the icon for this window used by GTK 2 backend.

This is simply passed to gtk_window_set_icon_name, see [http://library.gnome.org/devel/gtk/stable/GtkWindow.html#gtk-window-set-icon-name]. This allows you to use an installed icon (in /usr/share/icons/ or ˜/.local/share/icons/) for your program. See [http://library.gnome.org/devel/integration-guide/stable/icons.html.en] for short information how and where to install your icons.

It's ignored on non-GTK 2 backends.

Public property Visible: boolean read FVisible write FVisible default true;

Should this window be actually displayed on the desktop. In all normal programs you want to leave this as True, as the main purpose of the window is to actually be visible and interactive on the desktop.

Setting this to False allows you to get an OpenGL context without showing anything on the desktop. This can be used for rendering and capturing OpenGL stuff without showing it on the desktop. One example is the --screenshot option of view3dscene, see [http://castle-engine.sourceforge.net/view3dscene.php#section_screenshot].

If you implement such thing, remember that you should not render and capture the normal front or back buffer contents. OpenGL makes no guarantee that a hidden window will have any allocated memory, so capturing hidden window contents isn't useful (you may get something valid, or you may get random / blank screen, depending on OS and GPU). However, you can create Framebuffer Object on modern GPUs, and capture it's contents. An example code snippet:

{ add CastleGLImages, CastleImages to your uses clause }

var
  ScreenshotRender: TGLRenderToTexture;
  Image: TRGBImage;
begin
  ScreenshotRender := TGLRenderToTexture.Create(Width, Height);
  try
    ScreenshotRender.Buffer := tbNone;
    ScreenshotRender.GLContextOpen;
    ScreenshotRender.RenderBegin;

    { render your stuff here }

    { capture the screen }
    glFlush;
    Image := SaveScreen_NoFlush(0, 0, Width, Height, GL_BACK);
    try
      SaveImage(Image, 'aaa.png');
    finally FreeAndNil(Image) end;

    ScreenshotRender.RenderEnd;
  finally FreeAndNil(ScreenshotRender) end;
end;

Public property Caption: string read FCaption write SetCaption;

Caption of the window. By default it's initialized to ProgramName. May be changed even when the window is already open.

Public property OnDraw: TDrawFunc read FOnDraw write FOnDraw;

Draw your window contents here.

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 yourself a redraw of the window by the PostRedisplay method, which will cause this event to be called at nearest good time.

Note that calling PostRedisplay while in EventDraw (OnDraw) is not ignored. It means that in a short time next EventDraw (OnDraw) will be called.

Public property OnBeforeDraw: TDrawFunc read FOnBeforeDraw write FOnBeforeDraw;

Always called right before EventDraw (OnDraw). These two events, EventBeforeDraw (OnBeforeDraw) and EventDraw (OnDraw), will be always called sequentially as a pair.

The only difference between these two events is that time spent in EventBeforeDraw (OnBeforeDraw) is NOT counted as "frame time" by Fps.FrameTime. This is useful when you have something that needs to be done from time to time right before OnDraw and that is very time-consuming. It such cases it is not desirable to put such time-consuming task inside OnDraw because this would cause a sudden big change in Fps.FrameTime value. So you can avoid this by putting this in OnBeforeDraw.

Public property OnResize: TWindowFunc read FOnResize write FOnResize;

Called when the window size (Width, Height) changes. It's also guaranteed to be called during Open, right after the EventOpen (OnOpen) event.

Our OpenGL context is already "current" when this event is called (MakeCurrent is done right before), like for other events. This is a good place to set OpenGL viewport and projection matrix.

See also ResizeAllowed.

Simple 2D OpenGL programs may want to register here simple Resize2D.

Public property OnClose: TWindowFunc read FOnClose write FOnClose;

Called when the window is closed, right before the OpenGL context is destroyed. This is your last chance to release OpenGL resources, like textures, shaders, display lists etc. This is a counterpart to OnOpen event.

Public property OnPress: TInputPressReleaseFunc read FOnPress write FOnPress;

Called when user presses a key or mouse button or moves mouse wheel.

Public property OnRelease: TInputPressReleaseFunc read FOnRelease write FOnRelease;

Called when user releases a pressed key or mouse button.

Details about key up events: It's called right after Pressed[Key] changed from true to false.

Key is never K_None.

C may be #0 is no representable character is released. When C is <> #0, we detected that some character is released. This is connected with setting Characters[C] from True to False.

Note that reporting characters for "key release" messages is not perfect, as various key combinations (sometimes more than one?) may lead to generating given character. We have some intelligent algorithm for this, used to make Characters table and to detect this C for OnRelease callback. The idea is that a character is released when the key that initially caused the press of this character is also released.

This solves in a determined way problems like "what happens if I press Shift, then X, then release Shift, then release X". (will "X" be correctly released as pressed and then released? yes. will small "x" be reported as released at the end? no, as it was never pressed.)

Public property OnCloseQuery: TWindowFunc read FOnCloseQuery write FOnCloseQuery;

Called when user tries to close the window. This is called when you use window manager features to close the window, like clicking on the "close" icon on the window frame or using Alt+F4 on most desktops. This is not called when you explicitly close the window by calling the Close method.

When this callback is not assigned, we will just let the window be closed. When it's assigned, the window will not closed — you should call here Close explicitly if you want to (for example, after asking user for confirmation "do you really want to quit?").

When handling this event, you must remember that user may try to close our window at any time. E.g. if you're implementing here somehing like showing user text "You cannot quit now" or asking user "Do you really want to quit" remember that while you display such message to user and you're processing events (e.g. looking for keypress "Yes" or "No"), user may try to close your window again.

CastleMessages unit offers some nice routines that you can safely use here, e.g. you can use it inside OnCloseQuery like

if MessageYesNo(Window, 'Are you sure you want to quit?') then Close;

Inside MessageYesNo, when we're processing events, and waiting for user's answer (yes or no), futher OnCloseQuery events will be ignored, so everything will work OK.

This event is also useful if you want to call Close(false) on closing the window (i.e. QuitWhenLastWindowClosed = false). By default, if this event is undefined, we call Close(true) when user tries to close the window.

Public property OnMouseMove : TMouseMoveFunc read FMouseMove write FMouseMove;

Called when mouse is moved. Remember you always have the currently pressed mouse buttons in MousePressed. When this is called, the MouseX, MouseY properties describe the previous mouse position, while callback parameters NewX, NewY describe the new mouse position.

Public property OnIdle: TWindowFunc read FOnIdle write FOnIdle;

Idle event is called for all open windows, all the time. It's called when we have no more events to process, and have nothing to do with the exception of redraw. Our idle events are called at least as regularly as redraw. This last condition is important — otherwise your game could get overwhelmed my messages (like mouse moves) and time-consuming redraw, and you would not have time to actually update animations in idle events.

Called at the same time when Application.OnIdle is called.

You should add code to this window's OnIdle event (not to TGLApplication.OnIdle) when you do something related to this window. For example when you check this window's Pressed keys state, or animate something displayed on this window. This allows various "modal boxes" and such (see CastleMessages) to nicely "pause" such processing by temporarily replacing OnIdle and other events of a window that displays a modal box.

Public property OnTimer: TWindowFunc read FOnTimer write FOnTimer;

Timer event is called approximately after each Application.TimerMilisec miliseconds passed.

Called at the same time when Application.OnTimer is called.

Public property AutoRedisplay: boolean read fAutoRedisplay write SetAutoRedisplay;

Should we automatically redraw the window all the time, without a need for PostRedisplay call. If True, window will behave like a redraw is always needed, and EventDraw (OnDraw) will be always called as often as posible. This may be a waste of OS resources, so don't use it, unless you know that you really have some animation displayed all the time.

Public property MainMenu: TMenu read FMainMenu write SetMainMenu;

Menu bar of this window. When not assigned, we have no menu bar.

Note that MainMenu.Caption will be ignored.

You can change this freely while Closed.

You can change this almost freely while not Closed: you can use various properties of TMenuEntry descendants (adding, deleting items from TMenu, changing Caption, Key, CharKey, Checked properties – anything) and you can change value of MainMenu BUT you must not change MainMenu <> nil state when the window is not Closed. I.e. if you called Open with MainMenu = nil, then MainMenu must stay nil unit Close. If you called Open with MainMenu <> nil, then you can assign other MainMenu values while not Closed, but only values <>nil. I.e. you can't set MainMenu to nil if you called Open with MainMenu <> nil. See castle_game_engine/examples/window/window_menu.lpr for demo of changing value of MainMenu while window is not Closed.

Note that MainMenu.Enabled is honoured (as well as Enabled for all menu items inside, of course). You can use this to disallow user from clicking on the whole menu. When MainMenu.Enabled = False then no MenuItem.DoCommand, no EventMenuCommand will be called when user presses some menu item. When user presses some keyboard shortcut for some menu item, no MenuItem.DoCommand and no EventMenuCommand will be called, but instead normal EventPress (OnPress) will be called.

When it is useful to set this to false? For example hen using CastleWindowModes. When you're changing modes (e.g. at the beginning of CastleMessages.MessageOk) you're temporary setting OnMenuCommand to nil, but this doesn't block TMenuItem.DoCommand functions. The only way to block menu from triggering ANY event is to set this to MainMenu.Enabled to False.

Public property OwnsMainMenu: boolean read FOwnsMainMenu write FOwnsMainMenu default true;

If true then in TCastleWindowBase destructor MainMenu will be destroyed too (if not nil, od course). Usually this is something useful.

Public property OnMenuCommand: TMenuCommandFunc read FOnMenuCommand write FOnMenuCommand;

Called each time user chooses some menu item and it's not handled in TMenuItem.DoCommand. By default, menu item handling is passed to TMenuItem.DoCommand. Only when it return False (not handled) then we call this window's event.

Public property MousePressed: TMouseButtons read FMousePressed;

Currently pressed mouse buttons. When this changes, you're always notified by OnMouseDown or OnMouseUp calls.

This value is always current, in particular it's already updated when we call events OnMouseDown and OnMouseUp.

Public property MouseX: integer read FMouseX;

Mouse position. This is the mouse position relative to this window, more precisely relative to the OpenGL control of this window.

Left-top corner is (0, 0), and right-bottom is (Width - 1, Height - 1). This is consistent with most window libraries (GTK, LCL etc.). Plese note that Y coordinate is reversed with respect to the typical OpenGL Ortho2D projection, if needed you'll have to adjust it (by using Height - MouseY).

Note that we have mouse capturing (when user presses and holds the mouse button, all the following mouse events are reported to this window, even when user moves the mouse outside of the window). This is typical of all window libraries (GTK, LCL etc.). This implicates that mouse positions are sometimes tracked also when mouse is outside the window, which means that mouse position may be outside the rectangle (0, 0) - (Width - 1, Height - 1), so it may even be negative.

In all situations the MouseX, MouseY is the latest known mouse position. The only exception is within EventMouseMove (and so, also in OnMouseMove callback): MouseX, MouseY is then the previous known mouse position, while new mouse position is provided as NewX, NewY arguments to EventMouseMove (and OnMouseMove).

Public property MouseY: integer read FMouseY;
 
Public property UserData: Pointer read FUserData write FUserData;

Place for your pointer, for any purposes. No code in this unit touches the value of this field. This is similar to TComponent.Tag property.

Public property Closed: boolean read FClosed default true;
 
Public property Pressed: TKeysPressed read FPressed;

Tracks which keys, characters, modifiers are pressed.

Public property Fps: TFramesPerSecond read FFps;

Frames per second measuring.


Generated by PasDoc 0.12.1 on 2013-02-04 20:26:53