Reference TGraphicsBox
Declared in Codebot.Render.Controls.pas on line 122
TGraphicsBox is a windowed control for hosting OpenGL graphics.
When its window is first shown the control creates an SDL window which fills it, and SDL creates the OpenGL context for that window. The SDL window covers the control, so the keyboard and mouse over it are read by SDL and not by the LCL. Before each frame the render thread reads the events of SDL and passes them on in three ways:
The LCL key and mouse events of the control, such as OnKeyDown and
OnMouseMove, are called on the main thread. The render thread waits for
them to finish before it goes on, so they see the same input as the
frame which follows. It only waits when one of the events has a handler.
OnMouseMove, are called on the main thread. The render thread waits for
them to finish before it goes on, so they see the same input as the
frame which follows. It only waits when one of the events has a handler.
OnInput is called on the render thread with each SDL event.
Keyboard, Mouse and Joysticks in Codebot.Hardware are scanned.
OnMouseEnter and OnMouseLeave do not occur.
The SDL window is given the keyboard focus when the control is given the focus or is clicked, and gives it back to the form when the control loses the focus. While it has the focus the LCL does not see keys, so the tab key and the shortcuts of the form are not processed.
The control runs its own render thread once its window is first shown. All rendering happens on that thread with the context current:
1. The thread makes the context current and creates a TRenderContext,
which Ctx returns on that thread, and the Canvas
2. OnRenderStart is called to create OpenGL resources
3. The events of SDL are read, the hardware is scanned, OnInput is
called for each event, then OnRender is called, and the buffers are
flipped. This repeats.
4. OnRenderStop is called to destroy OpenGL resources. It is only called
if OnRenderStart completed.
5. The Canvas and the render context are destroyed, freeing any objects
the render context manages, and the context is released
which Ctx returns on that thread, and the Canvas
2. OnRenderStart is called to create OpenGL resources
3. The events of SDL are read, the hardware is scanned, OnInput is
called for each event, then OnRender is called, and the buffers are
flipped. This repeats.
4. OnRenderStop is called to destroy OpenGL resources. It is only called
if OnRenderStart completed.
5. The Canvas and the render context are destroyed, freeing any objects
the render context manages, and the context is released
The thread is stopped and waited for before the window handle is destroyed.
Because the events run on the render thread they must not access LCL controls directly. Use TThread.Queue or TThread.Synchronize to reach the main thread.
If any of the events raise an exception the thread stops, Failed becomes True, ErrorMessage holds the message, and OnFailed is called on the main thread.
The control can also run a step thread with StartStepping, which calls a step event at a fixed rate apart from rendering, such as to simulate physics. The step thread is stopped before the render thread when the window handle is destroyed, and an exception raised by the step event stops it in the same way as the render thread.
TGraphicsBox = class(TWinControl)
protected
class procedure WSRegisterClass; override;
procedure DestroyWnd; override;
procedure Resize; override;
procedure PaintWindow(DC: HDC); override;
procedure Paint; virtual;
{ ControlCanvas is used to paint the control when it cannot render }
property ControlCanvas: TControlCanvas read FCanvas;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure EraseBackground(DC: HDC); override;
{ BeginFrame begins canvas drawing using the canvas back buffer }
procedure BeginFrame;
{ EndFrame ends canvas drawing using the canvas back buffer }
procedure EndFrame;
{ Flip alternates between beginning and ending a frame of canvas drawing
sized to the rendering area of the context }
procedure Flip;
{ StartStepping runs a step thread which calls OnStep every Interval
seconds. Steps missed while the thread was busy are caught up, up to a
quarter of a second. A running step thread is stopped first. Call it from
the render thread or from the main thread while not rendering. }
procedure StartStepping(Interval: Double; OnStep: TGraphicsStepEvent);
{ StopStepping stops and waits for the step thread }
procedure StopStepping;
{ Canvas draws vector graphics using the context. It is created on the
render thread immediately before OnRenderStart and destroyed immediately
after OnRenderStop. It is nil outside of that period and should only be
used from the render thread. }
property Canvas: ICanvas read FRenderCanvas;
{ Context is only valid while Rendering is True. It is current on the render
thread and must not be made current on other threads. }
property Context: IOpenGLContext read GetContext;
{ Rendering is True from when the render thread is started, immediately
after a window is first shown, until the render thread is stopped,
immediately before the window handle is destroyed }
property Rendering: Boolean read FRendering;
{ Stepping is True while the step thread is running }
property Stepping: Boolean read GetStepping;
{ Failed is True when a context failed the creation step or when the render
thread stopped because of an exception. Creation failure is caused by
unsupported options and is distinctly different from OpenGLInfo.IsValid. }
property Failed: Boolean read FFailed;
{ ErrorMessage holds the message of the exception which stopped the render
thread }
property ErrorMessage: string read FErrorMessage;
{ OnInput fires on the render thread before OnRender for each key, text,
mouse and wheel event of the control. Assign it while not rendering. }
property OnInput: TGraphicsInputEvent read FOnInput write FOnInput;
published
property Align;
property Anchors;
property BorderSpacing;
property Constraints;
property Enabled;
property TabStop;
property Visible;
property OnClick;
property OnDblClick;
property OnKeyDown;
property OnKeyUp;
property OnUTF8KeyPress;
property OnMouseDown;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseMove;
property OnMouseUp;
property OnMouseWheel;
property OnResize;
{ Options are used once immediately before a context is created }
property Options: TGraphicsBoxOptions read FOptions write SetOptions;
{ OnFailed fires on the main thread after a context failed the creation step
or the render thread stopped because of an exception }
property OnFailed: TNotifyEvent read FOnFailed write FOnFailed;
{ OnRenderStart fires on the render thread with the context current after
the render context and Canvas are created }
property OnRenderStart: TNotifyEvent read FOnRenderStart write FOnRenderStart;
{ OnRenderStop fires on the render thread with the context current before
the Canvas and render context are destroyed }
property OnRenderStop: TNotifyEvent read FOnRenderStop write FOnRenderStop;
{ OnRender fires repeatedly on the render thread with the context current.
Do not access other controls from OnRender. Use TThread.Queue to send
information to the main thread. }
property OnRender: TGraphicsRenderEvent read FOnRender write FOnRender;
end;See also
ICanvas in Codebot.Render.Graphics.pas
IOpenGLContext in Codebot.OpenGL.pas