123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- //
- // The multimedia graphics platform GLScene https://github.com/glscene
- //
- unit GLS.HUDObjects;
- (* GLScene objects that get rendered in 2D coordinates *)
- interface
- {$I GLScene.inc}
- uses
- Winapi.OpenGL,
- System.Classes,
- Vcl.StdCtrls,
- GLS.OpenGLTokens,
- GLS.Scene,
- GLS.VectorTypes,
- GLS.Coordinates,
- GLS.PersistentClasses,
- GLS.VectorGeometry,
- GLS.Objects,
- GLS.BitmapFont,
- GLS.Color,
- GLS.RenderContextInfo,
- GLS.Material,
- GLS.Texture;
- type
- (*
- A rectangular area, NOT perspective projected.
- (x, y) coordinates map directly to the viewport (in pixels) and refer
- the center of the area.
- The coordinate system is that of an equivalent TCanvas, ie. top-left
- point is the origin (0, 0).
- The z component is ignored and Z-Buffer is disabled when rendering.
- Using TGLHUDSprite in 2D only scenes :
- The most convenient way to use a TGLHUDSprite as a simple 2D sprite with
- blending capabilities (transparency or additive), is to set the texture
- mode to tmModulate, in FrontProperties, to use the Emission color to
- control coloring/intensity, and finally use the Diffuse color's alpha
- to control transparency (while setting the other RGB components to 0).
- You can also control aplha-blending by defining a <1 value in the sprite's
- AlphaChannel field. This provides you with hardware accelerated,
- alpha-blended blitting.
- Note : since TGLHUDSprite works in absolute coordinates, TGLProxyObject
- can't be used to duplicate an hud sprite.
- *)
- TGLHUDSprite = class(TGLSprite)
- private
- FXTiles, FYTiles: Integer;
- function StoreWidth: Boolean;
- function StoreHeight: Boolean;
- protected
- procedure SetXTiles(const val: Integer);
- procedure SetYTiles(const val: Integer);
- public
- constructor Create(AOwner: TComponent); override;
- procedure DoRender(var rci: TGLRenderContextInfo;
- renderSelf, renderChildren: Boolean); override;
- published
- property XTiles: Integer read FXTiles write SetXTiles default 1;
- property YTiles: Integer read FYTiles write SetYTiles default 1;
- // Redeclare them with new default values.
- property Width stored StoreWidth;
- property Height stored StoreHeight;
- end;
- (*
- A 2D text displayed and positionned in 2D coordinates.
- The HUDText uses a character font defined and stored by a TGLBitmapFont
- component. The text can be scaled and rotated (2D), the layout and
- alignment can also be controled.
- *)
- TGLHUDText = class(TGLImmaterialSceneObject)
- private
- FBitmapFont: TGLCustomBitmapFont;
- FText: UnicodeString;
- FRotation: Single;
- FAlignment: TAlignment;
- FLayout: TTextLayout;
- FModulateColor: TGLColor;
- protected
- procedure SetBitmapFont(const val: TGLCustomBitmapFont);
- procedure SetText(const val: UnicodeString);
- procedure SetRotation(const val: Single);
- procedure SetAlignment(const val: TAlignment);
- procedure SetLayout(const val: TTextLayout);
- procedure SetModulateColor(const val: TGLColor);
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); override;
- procedure RenderTextAtPosition(const X, Y, Z: Single;
- var rci: TGLRenderContextInfo);
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure DoRender(var rci: TGLRenderContextInfo;
- renderSelf, renderChildren: Boolean); override;
- published
- (*
- Refers the bitmap font to use.
- The referred bitmap font component stores and allows access to
- individual character bitmaps.
- *)
- property BitmapFont: TGLCustomBitmapFont read FBitmapFont
- write SetBitmapFont;
- (*
- Text to render.
- Be aware that only the characters available in the bitmap font will
- be rendered. CR LF sequences are allowed.
- *)
- property Text: UnicodeString read FText write SetText;
- // Rotation angle in degrees (2d).
- property Rotation: Single read FRotation write SetRotation;
- (* Controls the text alignment (horizontal).
- Possible values : taLeftJustify, taRightJustify, taCenter *)
- property Alignment: TAlignment read FAlignment write SetAlignment
- default taLeftJustify;
- (* Controls the text layout (vertical).
- Possible values : tlTop, tlCenter, tlBottom *)
- property Layout: TTextLayout read FLayout write SetLayout default tlTop;
- // Color modulation, can be used for fade in/out too.
- property ModulateColor: TGLColor read FModulateColor write SetModulateColor;
- end;
- (* Position (X, Y and X) is in absolute coordinates. This component converts
- them to screen coordinates and renderes text there. *)
- TGLAbsoluteHUDText = class(TGLHUDText)
- public
- procedure DoRender(var rci: TGLRenderContextInfo;
- renderSelf, renderChildren: Boolean); override;
- end;
- (*
- Position (X and Y) is expected in a [0..1] range (from Screen size)
- This component converts this position to the actual screen position and
- renders the text there. This way a HUD text always appears to be in the
- the same place, regardless of the currect screen resolution.
- Note: this still does not solve the font scaling problem.
- *)
- TGLResolutionIndependantHUDText = class(TGLHUDText)
- public
- procedure DoRender(var rci: TGLRenderContextInfo;
- renderSelf, renderChildren: Boolean); override;
- constructor Create(AOwner: TComponent); override;
- end;
- // ------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------
- uses
- GLS.Context,
- GLS.State,
- GLS.XOpenGL;
- // ------------------
- // ------------------ TGLHUDSprite ------------------
- // ------------------
- constructor TGLHUDSprite.Create(AOwner: TComponent);
- begin
- inherited;
- ObjectStyle := ObjectStyle + [osDirectDraw, osNoVisibilityCulling];
- Width := 16;
- Height := 16;
- FXTiles := 1;
- FYTiles := 1;
- end;
- procedure TGLHUDSprite.SetXTiles(const val: Integer);
- begin
- if val <> FXTiles then
- begin
- FXTiles := val;
- StructureChanged;
- end;
- end;
- procedure TGLHUDSprite.SetYTiles(const val: Integer);
- begin
- if val <> FYTiles then
- begin
- FYTiles := val;
- StructureChanged;
- end;
- end;
- procedure TGLHUDSprite.DoRender(var rci: TGLRenderContextInfo;
- renderSelf, renderChildren: Boolean);
- var
- vx, vy, vx1, vy1, f: Single;
- u0, v0, u1, v1: Integer;
- begin
- if rci.ignoreMaterials then
- Exit;
- Material.Apply(rci);
- repeat
- if AlphaChannel <> 1 then
- begin
- if stLighting in rci.GLStates.States then
- rci.GLStates.SetGLMaterialAlphaChannel(GL_FRONT, AlphaChannel)
- else
- with Material.GetActualPrimaryMaterial.FrontProperties.Diffuse do
- gl.Color4f(Red, Green, Blue, AlphaChannel);
- end;
- // Prepare matrices
- gl.MatrixMode(GL_MODELVIEW);
- gl.PushMatrix;
- gl.LoadMatrixf(@TGLSceneBuffer(rci.buffer).BaseProjectionMatrix);
- if rci.renderDPI = 96 then
- f := 1
- else
- f := rci.renderDPI / 96;
- gl.Scalef(2 / rci.viewPortSize.cx, 2 / rci.viewPortSize.cy, 1);
- gl.Translatef(f * Position.X - rci.viewPortSize.cx * 0.5,
- rci.viewPortSize.cy * 0.5 - f * Position.Y, Position.Z);
- if Rotation <> 0 then
- gl.Rotatef(Rotation, 0, 0, 1);
- gl.MatrixMode(GL_PROJECTION);
- gl.PushMatrix;
- gl.LoadIdentity;
- rci.GLStates.Disable(stDepthTest);
- rci.GLStates.DepthWriteMask := False;
- // precalc coordinates
- vx := -Width * 0.5 * f;
- vx1 := vx + Width * f;
- vy := +Height * 0.5 * f;
- vy1 := vy - Height * f;
- // Texture coordinates
- if MirrorU then
- begin
- u0 := FXTiles;
- u1 := 0;
- end
- else
- begin
- u0 := 0;
- u1 := FXTiles;
- end;
- if MirrorV then
- begin
- v0 := FYTiles;
- v1 := 0;
- end
- else
- begin
- v0 := 0;
- v1 := FYTiles;
- end;
- // issue quad
- gl.Begin_(GL_QUADS);
- gl.Normal3fv(@YVector);
- xgl.TexCoord2f(u0, v0);
- gl.Vertex2f(vx, vy1);
- xgl.TexCoord2f(u1, v0);
- gl.Vertex2f(vx1, vy1);
- xgl.TexCoord2f(u1, v1);
- gl.Vertex2f(vx1, vy);
- xgl.TexCoord2f(u0, v1);
- gl.Vertex2f(vx, vy);
- gl.End_;
- // restore state
- gl.PopMatrix;
- gl.MatrixMode(GL_MODELVIEW);
- gl.PopMatrix;
- until not Material.UnApply(rci);
- if Count > 0 then
- Self.renderChildren(0, Count - 1, rci);
- end;
- function TGLHUDSprite.StoreHeight: Boolean;
- begin
- Result := Abs(Height - 16) > 0.001;
- end;
- function TGLHUDSprite.StoreWidth: Boolean;
- begin
- Result := Abs(Height - 16) > 0.001;
- end;
- // ------------------
- // ------------------ TGLHUDText ------------------
- // ------------------
- constructor TGLHUDText.Create(AOwner: TComponent);
- begin
- inherited;
- ObjectStyle := ObjectStyle + [osDirectDraw, osNoVisibilityCulling];
- FModulateColor := TGLColor.CreateInitialized(Self, clrWhite);
- end;
- destructor TGLHUDText.Destroy;
- begin
- FModulateColor.Free;
- BitmapFont := nil;
- inherited;
- end;
- procedure TGLHUDText.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- if (Operation = opRemove) and (AComponent = FBitmapFont) then
- BitmapFont := nil;
- inherited;
- end;
- procedure TGLHUDText.SetBitmapFont(const val: TGLCustomBitmapFont);
- begin
- if val <> FBitmapFont then
- begin
- if Assigned(FBitmapFont) then
- FBitmapFont.UnRegisterUser(Self);
- FBitmapFont := val;
- if Assigned(FBitmapFont) then
- begin
- FBitmapFont.RegisterUser(Self);
- FBitmapFont.FreeNotification(Self);
- end;
- StructureChanged;
- end;
- end;
- procedure TGLHUDText.SetText(const val: UnicodeString);
- begin
- FText := val;
- StructureChanged;
- end;
- procedure TGLHUDText.SetRotation(const val: Single);
- begin
- FRotation := val;
- StructureChanged;
- end;
- procedure TGLHUDText.SetAlignment(const val: TAlignment);
- begin
- FAlignment := val;
- StructureChanged;
- end;
- procedure TGLHUDText.SetLayout(const val: TTextLayout);
- begin
- FLayout := val;
- StructureChanged;
- end;
- procedure TGLHUDText.SetModulateColor(const val: TGLColor);
- begin
- FModulateColor.Assign(val);
- end;
- procedure TGLHUDText.RenderTextAtPosition(const X, Y, Z: Single;
- var rci: TGLRenderContextInfo);
- var
- f: Single;
- begin
- if Assigned(FBitmapFont) and (Text <> '') then
- begin
- rci.GLStates.PolygonMode := pmFill;
- // Prepare matrices
- gl.MatrixMode(GL_MODELVIEW);
- gl.PushMatrix;
- gl.LoadMatrixf(@TGLSceneBuffer(rci.buffer).BaseProjectionMatrix);
- f := rci.renderDPI / 96;
- gl.Scalef(2 / rci.viewPortSize.cx, 2 / rci.viewPortSize.cy, 1);
- gl.Translatef(X * f - rci.viewPortSize.cx / 2, rci.viewPortSize.cy / 2 -
- Y * f, Z);
- if FRotation <> 0 then
- gl.Rotatef(FRotation, 0, 0, 1);
- gl.Scalef(Scale.DirectX * f, Scale.DirectY * f, 1);
- gl.MatrixMode(GL_PROJECTION);
- gl.PushMatrix;
- gl.LoadIdentity;
- rci.GLStates.Disable(stDepthTest);
- // render text
- FBitmapFont.RenderString(rci, Text, FAlignment, FLayout,
- FModulateColor.Color);
- // restore state
- rci.GLStates.Enable(stDepthTest);
- gl.PopMatrix;
- gl.MatrixMode(GL_MODELVIEW);
- gl.PopMatrix;
- end;
- end;
- procedure TGLHUDText.DoRender(var rci: TGLRenderContextInfo;
- renderSelf, renderChildren: Boolean);
- begin
- RenderTextAtPosition(Position.X, Position.Y, Position.Z, rci);
- if Count > 0 then
- Self.renderChildren(0, Count - 1, rci);
- end;
- // ------------------
- // ------------------ TGLResolutionIndependantHUDText ------------------
- // ------------------
- constructor TGLResolutionIndependantHUDText.Create(AOwner: TComponent);
- begin
- inherited;
- Position.X := 0.5;
- Position.Y := 0.5;
- end;
- procedure TGLResolutionIndependantHUDText.DoRender(var rci: TGLRenderContextInfo;
- renderSelf, renderChildren: Boolean);
- begin
- RenderTextAtPosition(Position.X * rci.viewPortSize.cx,
- Position.Y * rci.viewPortSize.cy, Position.Z, rci);
- if Count > 0 then
- Self.renderChildren(0, Count - 1, rci);
- end;
- // ------------------
- // ------------------ TGLAbsoluteHUDText ------------------
- // ------------------
- procedure TGLAbsoluteHUDText.DoRender(var rci: TGLRenderContextInfo;
- renderSelf, renderChildren: Boolean);
- var
- Temp: TAffineVector;
- begin
- Temp := TGLSceneBuffer(rci.buffer).WorldToScreen(Self.AbsoluteAffinePosition);
- Temp.Y := rci.viewPortSize.cy - Temp.Y;
- RenderTextAtPosition(Temp.X, Temp.Y, Temp.Z, rci);
- if Count > 0 then
- Self.renderChildren(0, Count - 1, rci);
- end;
- // ------------------------------------------------------------------
- initialization
- // ------------------------------------------------------------------
- RegisterClasses([TGLHUDText, TGLHUDSprite, TGLResolutionIndependantHUDText,
- TGLAbsoluteHUDText]);
- end.
|