GLGui.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. unit GLGui;
  5. (* Windows management classes and structures *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. Winapi.OpenGL,
  10. System.Classes,
  11. System.SysUtils,
  12. System.Types,
  13. OpenGLTokens,
  14. GLVectorTypes,
  15. GLScene,
  16. GLBitmapFont,
  17. GLMaterial,
  18. GLCrossPlatform,
  19. GLContext,
  20. GLPersistentClasses,
  21. GLVectorGeometry,
  22. GLCoordinates,
  23. GLBaseClasses;
  24. type
  25. TGLBaseGuiObject = class(TGLBaseSceneObject)
  26. private
  27. FRecursiveVisible: Boolean;
  28. FWidth: Single;
  29. FHeight: Single;
  30. protected
  31. // self notification on hide. Also notifies children.
  32. procedure NotifyHide; virtual;
  33. // child notification on show. Also notifies children.
  34. procedure NotifyShow; virtual;
  35. procedure SetLeft(const Value: TGLFloat);
  36. function GetLeft: TGLFloat;
  37. procedure SetTop(const Value: TGLFloat);
  38. function GetTop: TGLFloat;
  39. procedure SetWidth(const val: Single);
  40. procedure SetHeight(const val: Single);
  41. procedure SetVisible(aValue: Boolean); override;
  42. public
  43. constructor Create(AOwner: TComponent); override;
  44. procedure AddChild(AChild: TGLBaseSceneObject); override;
  45. procedure Insert(aIndex: Integer; AChild: TGLBaseSceneObject); override;
  46. // GuiComponent Width in 3D world units.
  47. property Width: Single read FWidth write SetWidth;
  48. // GuiComponent Height in 3D world units.
  49. property Height: Single read FHeight write SetHeight;
  50. // GuiComponent Left in 3D world units.
  51. property Left: TGLFloat read GetLeft write SetLeft;
  52. // GuiComponent Top in 3D world units.
  53. property Top: TGLFloat read GetTop write SetTop;
  54. property RecursiveVisible: Boolean read FRecursiveVisible;
  55. end;
  56. TGUIAlignments = (GLAlTopLeft, GLAlTop, GLAlTopRight, GLAlLeft, GLAlCenter,
  57. GLAlRight, GLAlBottomLeft, GLAlBottom, GLAlBottomRight, GLAlBorder);
  58. TGUIRect = record
  59. X1: TGLFloat;
  60. Y1: TGLFloat;
  61. X2: TGLFloat;
  62. Y2: TGLFloat;
  63. XTiles: TGLFloat;
  64. YTiles: TGLFloat;
  65. end;
  66. TGUIDrawResult = array [TGUIAlignments] of TGUIRect;
  67. TGLGuiElementName = string;
  68. TGLGuiElement = class(TCollectionItem)
  69. private
  70. FTopLeft: TGLCoordinates2;
  71. FBottomRight: TGLCoordinates2;
  72. FScale: TGLCoordinates2;
  73. FAlign: TGUIAlignments;
  74. FName: TGLGuiElementName;
  75. protected
  76. function GetDisplayName: string; override;
  77. procedure SetName(const val: TGLGuiElementName);
  78. public
  79. constructor Create(Collection: TCollection); override;
  80. destructor Destroy; override;
  81. procedure AssignTo(Dest: TPersistent); override;
  82. published
  83. property TopLeft: TGLCoordinates2 read FTopLeft write FTopLeft;
  84. property BottomRight: TGLCoordinates2 read FBottomRight write FBottomRight;
  85. property Scale: TGLCoordinates2 read FScale write FScale;
  86. property Align: TGUIAlignments read FAlign write FAlign;
  87. property Name: TGLGuiElementName read FName write SetName;
  88. end;
  89. TGLGuiComponent = class;
  90. TGLGuiElementList = class(TOwnedCollection)
  91. private
  92. FGuiComponent: TGLGuiComponent;
  93. protected
  94. procedure SetItems(index: Integer; const val: TGLGuiElement);
  95. function GetItems(index: Integer): TGLGuiElement;
  96. public
  97. constructor Create(AOwner: TGLGuiComponent);
  98. procedure AssignTo(Dest: TPersistent); override;
  99. function GetOwner: TPersistent; override;
  100. function IndexOf(const Item: TGLGuiElement): Integer;
  101. property Items[index: Integer]: TGLGuiElement read GetItems
  102. write SetItems; default;
  103. end;
  104. TGLGuiComponentName = string;
  105. TGLGuiComponentList = class;
  106. TGLGuiComponent = class(TCollectionItem)
  107. private
  108. FElements: TGLGuiElementList;
  109. FName: TGLGuiComponentName;
  110. protected
  111. function GetDisplayName: string; override;
  112. procedure SetName(const val: TGLGuiComponentName);
  113. public
  114. constructor Create(Collection: TCollection); override;
  115. destructor Destroy; override;
  116. procedure AssignTo(Dest: TPersistent); override;
  117. procedure RenderToArea(X1, Y1, X2, Y2: TGLFloat; var Res: TGUIDrawResult;
  118. Refresh: Boolean = True; Scale: TGLFloat = 1);
  119. function GetOwnerList: TGLGuiComponentList;
  120. property Owner: TGLGuiComponentList read GetOwnerList;
  121. published
  122. property Elements: TGLGuiElementList read FElements write FElements;
  123. property Name: TGLGuiComponentName read FName write SetName;
  124. end;
  125. TGLGuiLayout = class;
  126. TGLGuiComponentList = class(TOwnedCollection)
  127. private
  128. FLayout: TGLGuiLayout;
  129. protected
  130. procedure SetItems(index: Integer; const val: TGLGuiComponent);
  131. function GetItems(index: Integer): TGLGuiComponent;
  132. public
  133. constructor Create(AOwner: TGLGuiLayout);
  134. function GetOwner: TPersistent; override;
  135. function FindItem(name: TGLGuiComponentName): TGLGuiComponent;
  136. property Items[index: Integer]: TGLGuiComponent read GetItems
  137. write SetItems; default;
  138. end;
  139. TGLGuiLayout = class(TGLUpdateableComponent)
  140. private
  141. FBitmapFont: TGLCustomBitmapFont;
  142. FMaterial: TGLMaterial;
  143. FGuiComponents: TGLGuiComponentList;
  144. FFileName: string;
  145. FGuiComponentList: TList;
  146. protected
  147. procedure Notification(AComponent: TComponent;
  148. Operation: TOperation); override;
  149. procedure SetFileName(newName: string);
  150. public
  151. constructor Create(AOwner: TComponent); override;
  152. destructor Destroy; override;
  153. procedure Assign(Source: TPersistent); override;
  154. procedure LoadFromStream(Stream: TStream);
  155. procedure LoadFromFile(FN: string);
  156. procedure Clear;
  157. procedure SaveToStream(Stream: TStream);
  158. procedure SaveToFile(FN: string);
  159. procedure AddGuiComponent(Component: TGLUpdateableComponent);
  160. procedure RemoveGuiComponent(Component: TGLUpdateableComponent);
  161. procedure NotifyChange(Sender: TObject); override;
  162. published
  163. property BitmapFont: TGLCustomBitmapFont read FBitmapFont write FBitmapFont;
  164. property Material: TGLMaterial read FMaterial write FMaterial;
  165. property GuiComponents: TGLGuiComponentList read FGuiComponents
  166. write FGuiComponents;
  167. property FileName: string read FFileName write SetFileName;
  168. end;
  169. const
  170. GuiNullRect: TGUIRect = (X1: 0.0; Y1: 0.0; X2: 0.0; Y2: 0.0; XTiles: 0.0;
  171. YTiles: 0.0);
  172. function IsInRect(const R: TGUIRect; X, Y: Single): Boolean; inline;
  173. // ------------------------------------------------------
  174. implementation
  175. // ------------------------------------------------------
  176. function IsInRect(const R: TGUIRect; X, Y: Single): Boolean; inline;
  177. begin
  178. Result := (R.X1 <= X) and (R.X2 >= X) and (R.Y1 <= Y) and (R.Y2 >= Y);
  179. end;
  180. // ------------------
  181. // ------------------ TGLBaseGuiObject ------------------
  182. // ------------------
  183. constructor TGLBaseGuiObject.Create(AOwner: TComponent);
  184. begin
  185. inherited Create(AOwner);
  186. FRecursiveVisible := Visible;
  187. end;
  188. procedure TGLBaseGuiObject.SetLeft(const Value: TGLFloat);
  189. var
  190. NewPosX: TGLFloat;
  191. i: Integer;
  192. Diff: TGLFloat;
  193. begin
  194. if Assigned(Parent) and (Parent is TGLBaseGuiObject) then
  195. NewPosX := (Parent as TGLBaseGuiObject).Position.X + Value
  196. else
  197. NewPosX := Value;
  198. if Position.X <> NewPosX then
  199. begin
  200. Diff := NewPosX - Position.X;
  201. Position.X := NewPosX;
  202. for i := 0 to Count - 1 do
  203. if Children[i] is TGLBaseGuiObject then
  204. begin
  205. (Children[i] as TGLBaseGuiObject).Left :=
  206. (Children[i] as TGLBaseGuiObject).Left + Diff;
  207. end;
  208. end;
  209. end;
  210. function TGLBaseGuiObject.GetLeft: TGLFloat;
  211. begin
  212. if Assigned(Parent) and (Parent is TGLBaseGuiObject) then
  213. Result := Position.X - (Parent as TGLBaseGuiObject).Position.X
  214. else
  215. Result := Position.X;
  216. end;
  217. procedure TGLBaseGuiObject.SetTop(const Value: TGLFloat);
  218. var
  219. NewPosY: TGLFloat;
  220. i: Integer;
  221. Diff: TGLFloat;
  222. begin
  223. if Assigned(Parent) and (Parent is TGLBaseGuiObject) then
  224. NewPosY := (Parent as TGLBaseGuiObject).Position.Y + Value
  225. else
  226. NewPosY := Value;
  227. if Position.Y <> NewPosY then
  228. begin
  229. Diff := NewPosY - Position.Y;
  230. Position.Y := NewPosY;
  231. for i := 0 to Count - 1 do
  232. if Children[i] is TGLBaseGuiObject then
  233. begin
  234. (Children[i] as TGLBaseGuiObject).Top :=
  235. (Children[i] as TGLBaseGuiObject).Top + Diff;
  236. end;
  237. end;
  238. end;
  239. function TGLBaseGuiObject.GetTop: TGLFloat;
  240. begin
  241. if Assigned(Parent) and (Parent is TGLBaseGuiObject) then
  242. Result := Position.Y - (Parent as TGLBaseGuiObject).Position.Y
  243. else
  244. Result := Position.Y;
  245. end;
  246. procedure TGLBaseGuiObject.SetWidth(const val: TGLFloat);
  247. begin
  248. if FWidth <> val then
  249. begin
  250. FWidth := val;
  251. NotifyChange(Self);
  252. end;
  253. end;
  254. procedure TGLBaseGuiObject.SetHeight(const val: TGLFloat);
  255. begin
  256. if FHeight <> val then
  257. begin
  258. FHeight := val;
  259. NotifyChange(Self);
  260. end;
  261. end;
  262. procedure TGLBaseGuiObject.NotifyHide;
  263. var
  264. child: TGLBaseSceneObject;
  265. xc: Integer;
  266. begin
  267. if RecursiveVisible then
  268. begin
  269. FRecursiveVisible := False;
  270. for xc := 0 to Count - 1 do
  271. begin
  272. child := Children[xc];
  273. if child is TGLBaseGuiObject then
  274. TGLBaseGuiObject(child).NotifyHide;
  275. end;
  276. end;
  277. end;
  278. procedure TGLBaseGuiObject.NotifyShow;
  279. var
  280. child: TGLBaseSceneObject;
  281. xc: Integer;
  282. begin
  283. if not RecursiveVisible then
  284. begin
  285. FRecursiveVisible := True;
  286. for xc := 0 to Count - 1 do
  287. begin
  288. child := Children[xc];
  289. if child is TGLBaseGuiObject then
  290. TGLBaseGuiObject(child).NotifyShow;
  291. end;
  292. end;
  293. end;
  294. procedure TGLBaseGuiObject.AddChild(AChild: TGLBaseSceneObject);
  295. begin
  296. inherited;
  297. if AChild is TGLBaseGuiObject then
  298. begin
  299. if RecursiveVisible then
  300. TGLBaseGuiObject(AChild).NotifyShow
  301. else
  302. TGLBaseGuiObject(AChild).NotifyHide;
  303. end;
  304. end;
  305. procedure TGLBaseGuiObject.Insert(aIndex: Integer; AChild: TGLBaseSceneObject);
  306. begin
  307. inherited;
  308. if AChild is TGLBaseGuiObject then
  309. begin
  310. if RecursiveVisible then
  311. TGLBaseGuiObject(AChild).NotifyShow
  312. else
  313. TGLBaseGuiObject(AChild).NotifyHide;
  314. end;
  315. end;
  316. procedure TGLBaseGuiObject.SetVisible(aValue: Boolean);
  317. begin
  318. if Visible <> aValue then
  319. begin
  320. inherited SetVisible(aValue);
  321. if aValue then
  322. begin
  323. if Parent <> nil then
  324. if Parent is TGLBaseGuiObject then
  325. begin
  326. if TGLBaseGuiObject(Parent).RecursiveVisible then
  327. NotifyShow;
  328. end
  329. else
  330. begin
  331. if Parent.Visible then
  332. NotifyShow;
  333. end;
  334. end
  335. else
  336. begin
  337. if RecursiveVisible then
  338. NotifyHide;
  339. end;
  340. end;
  341. end;
  342. constructor TGLGuiLayout.Create(AOwner: TComponent);
  343. begin
  344. FGuiComponentList := TList.Create;
  345. inherited;
  346. FGuiComponents := TGLGuiComponentList.Create(Self);
  347. FMaterial := TGLMaterial.Create(Self);
  348. end;
  349. destructor TGLGuiLayout.Destroy;
  350. begin
  351. Clear;
  352. FMaterial.Free;
  353. FGuiComponents.Free;
  354. inherited;
  355. FGuiComponentList.Free;
  356. end;
  357. procedure TGLGuiLayout.SetFileName(newName: string);
  358. begin
  359. if newName <> FFileName then
  360. begin
  361. FFileName := newName;
  362. if FileExists(FFileName) then
  363. begin
  364. Clear;
  365. LoadFromFile(FFileName);
  366. end;
  367. end;
  368. end;
  369. procedure TGLGuiLayout.LoadFromFile(FN: string);
  370. var
  371. Stream: TMemoryStream;
  372. begin
  373. Stream := TMemoryStream.Create;
  374. try
  375. Stream.LoadFromFile(FN);
  376. LoadFromStream(Stream);
  377. FFileName := FN;
  378. finally
  379. Stream.Free;
  380. end;
  381. end;
  382. procedure TGLGuiLayout.SaveToFile(FN: string);
  383. var
  384. Stream: TMemoryStream;
  385. begin
  386. Stream := TMemoryStream.Create;
  387. try
  388. SaveToStream(Stream);
  389. Stream.SaveToFile(FN);
  390. FFileName := FN;
  391. finally
  392. Stream.Free;
  393. end;
  394. end;
  395. procedure TGLGuiLayout.AddGuiComponent(Component: TGLUpdateableComponent);
  396. begin
  397. if FGuiComponentList.IndexOf(Component) < 0 then
  398. begin
  399. FreeNotification(Component);
  400. FGuiComponentList.Add(Component);
  401. end;
  402. end;
  403. procedure TGLGuiLayout.RemoveGuiComponent(Component: TGLUpdateableComponent);
  404. begin
  405. FGuiComponentList.Remove(Component);
  406. RemoveFreeNotification(Component);
  407. end;
  408. procedure TGLGuiLayout.Assign(Source: TPersistent);
  409. var
  410. LLayout: TGLGuiLayout;
  411. LComponent: TGLGuiComponent;
  412. i: Integer;
  413. begin
  414. if Source is TGLGuiLayout then
  415. begin
  416. LLayout := TGLGuiLayout(Source);
  417. FBitmapFont := LLayout.FBitmapFont;
  418. FMaterial.Assign(LLayout.Material);
  419. FFileName := LLayout.FFileName;
  420. Clear;
  421. for i := 0 to LLayout.FGuiComponents.Count - 1 do
  422. begin
  423. LComponent := TGLGuiComponent(FGuiComponents.Add);
  424. LLayout.FGuiComponents[i].AssignTo(LComponent);
  425. LComponent.name := LLayout.FGuiComponents[i].name;
  426. end;
  427. for i := 0 to FGuiComponentList.Count - 1 do
  428. TGLUpdateableComponent(FGuiComponentList[i]).RemoveFreeNotification(Self);
  429. FGuiComponentList.Assign(LLayout.FGuiComponentList);
  430. for i := 0 to FGuiComponentList.Count - 1 do
  431. TGLUpdateableComponent(FGuiComponentList[i]).FreeNotification(Self);
  432. end
  433. else
  434. inherited; // Assign Error
  435. end;
  436. procedure TGLGuiLayout.Clear;
  437. var
  438. xc: Integer;
  439. begin
  440. for xc := FGuiComponents.Count - 1 downto 0 do
  441. begin
  442. FGuiComponents.Delete(xc);
  443. end;
  444. NotifyChange(Self);
  445. end;
  446. procedure TGLGuiLayout.NotifyChange(Sender: TObject);
  447. var
  448. xc: Integer;
  449. begin
  450. inherited;
  451. for xc := FGuiComponentList.Count - 1 downto 0 do
  452. TGLUpdateableComponent(FGuiComponentList[xc]).NotifyChange(Self);
  453. end;
  454. procedure TGLGuiLayout.LoadFromStream(Stream: TStream);
  455. var
  456. TmpComponent: TGLGuiComponent;
  457. xc, YC, ZC: Integer;
  458. TmpElement: TGLGuiElement;
  459. TmpAlignment: TGUIAlignments;
  460. Version: Integer;
  461. Data: TGLBinaryReader;
  462. begin
  463. Data := TGLBinaryReader.Create(Stream);
  464. try
  465. Version := Data.ReadInteger;
  466. if Version <> 1 then
  467. Exit;
  468. for xc := 0 to Data.ReadInteger - 1 do
  469. begin
  470. TmpComponent := FGuiComponents.Add as TGLGuiComponent;
  471. TmpComponent.FName := Data.ReadString;
  472. for YC := 0 to Data.ReadInteger - 1 do
  473. begin
  474. TmpElement := TmpComponent.FElements.Add as TGLGuiElement;
  475. TmpElement.FName := Data.ReadString;
  476. TmpElement.FTopLeft.X := Data.ReadFloat;
  477. TmpElement.FTopLeft.Y := Data.ReadFloat;
  478. TmpElement.FTopLeft.Z := Data.ReadFloat;
  479. TmpElement.FBottomRight.X := Data.ReadFloat;
  480. TmpElement.FBottomRight.Y := Data.ReadFloat;
  481. TmpElement.FBottomRight.Z := Data.ReadFloat;
  482. TmpElement.FScale.X := Data.ReadFloat;
  483. TmpElement.FScale.Y := Data.ReadFloat;
  484. TmpElement.FScale.Z := Data.ReadFloat;
  485. for ZC := 0 to Data.ReadInteger - 1 do
  486. begin
  487. TmpAlignment := TGUIAlignments(Data.ReadInteger);
  488. TmpElement.FAlign := TmpAlignment;
  489. end;
  490. end;
  491. end;
  492. finally
  493. Data.Free;
  494. end;
  495. NotifyChange(Self);
  496. end;
  497. procedure TGLGuiLayout.SaveToStream(Stream: TStream);
  498. var
  499. TmpComponent: TGLGuiComponent;
  500. Alignments, xc, YC: Integer;
  501. TmpElement: TGLGuiElement;
  502. TmpAlignment: TGUIAlignments;
  503. Data: TGLBinaryWriter;
  504. begin
  505. Data := TGLBinaryWriter.Create(Stream);
  506. try
  507. Data.WriteInteger(1);
  508. Data.WriteInteger(FGuiComponents.Count);
  509. for xc := 0 to FGuiComponents.Count - 1 do
  510. begin
  511. TmpComponent := FGuiComponents.Items[xc];
  512. Data.WriteString(TmpComponent.FName);
  513. Data.WriteInteger(TmpComponent.FElements.Count);
  514. for YC := 0 to TmpComponent.FElements.Count - 1 do
  515. begin
  516. TmpElement := TmpComponent.FElements.Items[YC];
  517. Data.WriteString(TmpElement.FName);
  518. Data.WriteFloat(TmpElement.FTopLeft.X);
  519. Data.WriteFloat(TmpElement.FTopLeft.Y);
  520. Data.WriteFloat(TmpElement.FTopLeft.Z);
  521. Data.WriteFloat(TmpElement.FBottomRight.X);
  522. Data.WriteFloat(TmpElement.FBottomRight.Y);
  523. Data.WriteFloat(TmpElement.FBottomRight.Z);
  524. Data.WriteFloat(TmpElement.FScale.X);
  525. Data.WriteFloat(TmpElement.FScale.Y);
  526. Data.WriteFloat(TmpElement.FScale.Z);
  527. Alignments := 0;
  528. for TmpAlignment := GLAlTopLeft to GLAlBorder do
  529. begin
  530. if TmpAlignment = TmpElement.FAlign then
  531. inc(Alignments);
  532. end;
  533. Data.WriteInteger(Alignments);
  534. for TmpAlignment := GLAlTopLeft to GLAlBorder do
  535. begin
  536. if TmpAlignment = TmpElement.FAlign then
  537. Data.WriteInteger(Integer(TmpAlignment));
  538. end;
  539. end;
  540. end;
  541. finally
  542. Data.Free;
  543. end;
  544. end;
  545. constructor TGLGuiComponentList.Create(AOwner: TGLGuiLayout);
  546. begin
  547. inherited Create(AOwner, TGLGuiComponent);
  548. FLayout := AOwner;
  549. end;
  550. function TGLGuiComponentList.GetOwner: TPersistent;
  551. begin
  552. Result := FLayout;
  553. end;
  554. procedure TGLGuiComponentList.SetItems(index: Integer;
  555. const val: TGLGuiComponent);
  556. begin
  557. inherited Items[index] := val;
  558. end;
  559. function TGLGuiComponentList.FindItem(name: TGLGuiComponentName)
  560. : TGLGuiComponent;
  561. var
  562. xc: Integer;
  563. gc: TGLGuiComponent;
  564. begin
  565. Result := nil;
  566. if Name = '' then
  567. Exit;
  568. for xc := 0 to Count - 1 do
  569. begin
  570. gc := Items[xc];
  571. if gc.FName = Name then
  572. begin
  573. Result := gc;
  574. Break;
  575. end;
  576. end;
  577. end;
  578. function TGLGuiComponentList.GetItems(index: Integer): TGLGuiComponent;
  579. begin
  580. Result := TGLGuiComponent(inherited Items[index]);
  581. end;
  582. procedure TGLGuiComponent.RenderToArea(X1, Y1, X2, Y2: TGLFloat;
  583. var Res: TGUIDrawResult; Refresh: Boolean = True; Scale: TGLFloat = 1);
  584. var
  585. xc: Integer;
  586. ThisElement: TGLGuiElement;
  587. W, H: TGLFloat;
  588. Len1, Len2: TGLFloat;
  589. Layout: TGLGuiLayout;
  590. LibMaterial: TGLLibMaterial;
  591. Material: TGLMaterial;
  592. TexWidth, TexHeight: TGLFloat;
  593. AlignCount: TGUIAlignments;
  594. procedure Prepare;
  595. begin
  596. Len1 := (ThisElement.FTopLeft.X - ThisElement.FBottomRight.X) *
  597. ThisElement.Scale.X * Scale;
  598. Len2 := (ThisElement.FTopLeft.Y - ThisElement.FBottomRight.Y) *
  599. ThisElement.Scale.Y * Scale;
  600. if Len1 < 0 then
  601. begin
  602. if Len2 < 0 then
  603. begin
  604. W := -Len1;
  605. H := -Len2;
  606. end
  607. else
  608. begin
  609. W := -Len1;
  610. H := Len2;
  611. end;
  612. end
  613. else
  614. begin
  615. if Len2 < 0 then
  616. begin
  617. W := Len1;
  618. H := -Len2;
  619. end
  620. else
  621. begin
  622. W := Len1;
  623. H := Len2;
  624. end;
  625. end;
  626. end;
  627. procedure RenderIt(var ARect: TGUIRect; AElement: TGLGuiElement);
  628. var
  629. xc: TGLFloat;
  630. YC: TGLFloat;
  631. XPos, X2Pos: TGLFloat;
  632. YPos, y2Pos: TGLFloat;
  633. tx1, ty1, tx2, ty2: TGLFloat;
  634. XTileSize, YTileSize: TGLFloat;
  635. tx3, ty3: TGLFloat;
  636. tx, ty: TGLFloat;
  637. begin
  638. if (ARect.XTiles = 1) and (ARect.YTiles = 1) then
  639. begin
  640. gl.TexCoord2f(AElement.TopLeft.X / TexWidth, -AElement.TopLeft.Y /
  641. TexHeight);
  642. gl.Vertex2f(ARect.X1, -ARect.Y1);
  643. gl.TexCoord2f(AElement.TopLeft.X / TexWidth, -AElement.BottomRight.Y /
  644. TexHeight);
  645. gl.Vertex2f(ARect.X1, -ARect.Y2);
  646. gl.TexCoord2f(AElement.BottomRight.X / TexWidth, -AElement.BottomRight.Y /
  647. TexHeight);
  648. gl.Vertex2f(ARect.X2, -ARect.Y2);
  649. gl.TexCoord2f(AElement.BottomRight.X / TexWidth,
  650. -AElement.TopLeft.Y / TexHeight);
  651. gl.Vertex2f(ARect.X2, -ARect.Y1);
  652. end
  653. else
  654. begin
  655. XTileSize := (ARect.X2 - ARect.X1) / ARect.XTiles;
  656. YTileSize := (ARect.Y2 - ARect.Y1) / ARect.YTiles;
  657. tx1 := AElement.TopLeft.X / TexWidth;
  658. ty1 := -AElement.TopLeft.Y / TexHeight;
  659. tx2 := AElement.BottomRight.X / TexWidth;
  660. ty2 := -AElement.BottomRight.Y / TexHeight;
  661. tx3 := (AElement.TopLeft.X + (AElement.BottomRight.X - AElement.TopLeft.X)
  662. * Frac(ARect.XTiles)) / TexWidth;
  663. ty3 := -(AElement.TopLeft.Y + (AElement.BottomRight.Y -
  664. AElement.TopLeft.Y) * Frac(ARect.YTiles)) / TexHeight;
  665. xc := ARect.XTiles;
  666. XPos := ARect.X1;
  667. tx := tx2;
  668. while xc > 0 do
  669. begin
  670. YC := ARect.YTiles;
  671. YPos := ARect.Y1;
  672. ty := ty2;
  673. if xc >= 1 then
  674. X2Pos := XPos + XTileSize
  675. else
  676. begin
  677. X2Pos := ARect.X2;
  678. tx := tx3;
  679. end;
  680. while YC > 0 do
  681. begin
  682. if YC >= 1 then
  683. y2Pos := YPos + YTileSize
  684. else
  685. begin
  686. y2Pos := ARect.Y2;
  687. ty := ty3;
  688. end;
  689. gl.TexCoord2f(tx1, ty1);
  690. gl.Vertex2f(XPos, -YPos);
  691. gl.TexCoord2f(tx1, ty);
  692. gl.Vertex2f(XPos, -y2Pos);
  693. gl.TexCoord2f(tx, ty);
  694. gl.Vertex2f(X2Pos, -y2Pos);
  695. gl.TexCoord2f(tx, ty1);
  696. gl.Vertex2f(X2Pos, -YPos);
  697. YC := YC - 1.0;
  698. YPos := y2Pos;
  699. end;
  700. xc := xc - 1.0;
  701. XPos := X2Pos;
  702. end;
  703. end;
  704. end;
  705. procedure RenderBorder(AElement: TGLGuiElement);
  706. var
  707. TmpElement: TGLGuiElement;
  708. begin
  709. TmpElement := TGLGuiElement.Create(nil);
  710. TmpElement.FTopLeft.X := ThisElement.FTopLeft.X;
  711. TmpElement.FTopLeft.Y := ThisElement.FTopLeft.Y;
  712. TmpElement.FBottomRight.X := ThisElement.FTopLeft.X + ThisElement.Scale.X;
  713. TmpElement.FBottomRight.Y := ThisElement.FTopLeft.Y + ThisElement.Scale.Y;
  714. TmpElement.Scale.SetPoint2D(1, 1);
  715. RenderIt(Res[GLAlTopLeft], TmpElement);
  716. TmpElement.FTopLeft.X := ThisElement.FTopLeft.X + ThisElement.Scale.X;
  717. TmpElement.FBottomRight.X := ThisElement.FBottomRight.X -
  718. ThisElement.Scale.X;
  719. RenderIt(Res[GLAlTop], TmpElement);
  720. TmpElement.FTopLeft.X := ThisElement.FBottomRight.X - ThisElement.Scale.X;
  721. TmpElement.FBottomRight.X := ThisElement.FBottomRight.X;
  722. RenderIt(Res[GLAlTopRight], TmpElement);
  723. TmpElement.FTopLeft.Y := ThisElement.FTopLeft.Y + ThisElement.Scale.Y;
  724. TmpElement.FBottomRight.Y := ThisElement.FBottomRight.Y -
  725. ThisElement.Scale.Y;
  726. RenderIt(Res[GLAlRight], TmpElement);
  727. TmpElement.FTopLeft.X := ThisElement.FBottomRight.X - ThisElement.Scale.X;
  728. TmpElement.FTopLeft.Y := ThisElement.FBottomRight.Y - ThisElement.Scale.Y;
  729. TmpElement.FBottomRight.X := ThisElement.FBottomRight.X;
  730. TmpElement.FBottomRight.Y := ThisElement.FBottomRight.Y;
  731. RenderIt(Res[GLAlBottomRight], TmpElement);
  732. TmpElement.FTopLeft.X := ThisElement.FTopLeft.X + ThisElement.Scale.X;
  733. TmpElement.FTopLeft.Y := ThisElement.FBottomRight.Y - ThisElement.Scale.Y;
  734. TmpElement.FBottomRight.X := ThisElement.FBottomRight.X -
  735. ThisElement.Scale.X;
  736. TmpElement.FBottomRight.Y := ThisElement.FBottomRight.Y;
  737. RenderIt(Res[GLAlBottom], TmpElement);
  738. TmpElement.FTopLeft.X := ThisElement.FTopLeft.X;
  739. TmpElement.FTopLeft.Y := ThisElement.FBottomRight.Y - ThisElement.Scale.Y;
  740. TmpElement.FBottomRight.X := ThisElement.FTopLeft.X + ThisElement.Scale.X;
  741. TmpElement.FBottomRight.Y := ThisElement.FBottomRight.Y;
  742. RenderIt(Res[GLAlBottomLeft], TmpElement);
  743. TmpElement.FTopLeft.X := ThisElement.FTopLeft.X;
  744. TmpElement.FTopLeft.Y := ThisElement.FTopLeft.Y + ThisElement.Scale.Y;
  745. TmpElement.FBottomRight.X := ThisElement.FTopLeft.X + ThisElement.Scale.X;
  746. TmpElement.FBottomRight.Y := ThisElement.FBottomRight.Y -
  747. ThisElement.Scale.Y;
  748. RenderIt(Res[GLAlLeft], TmpElement);
  749. TmpElement.FTopLeft.X := ThisElement.FTopLeft.X + ThisElement.Scale.X;
  750. TmpElement.FTopLeft.Y := ThisElement.FTopLeft.Y + ThisElement.Scale.Y;
  751. TmpElement.FBottomRight.X := ThisElement.FBottomRight.X -
  752. ThisElement.Scale.X;
  753. TmpElement.FBottomRight.Y := ThisElement.FBottomRight.Y -
  754. ThisElement.Scale.Y;
  755. RenderIt(Res[GLAlCenter], TmpElement);
  756. end;
  757. begin
  758. Layout := ((GetOwner as TGLGuiComponentList).GetOwner as TGLGuiLayout);
  759. Material := nil;
  760. if Assigned(Layout.Material.MaterialLibrary) and
  761. (Layout.Material.MaterialLibrary is TGLMaterialLibrary) and
  762. (Layout.Material.LibMaterialName <> '') then
  763. begin
  764. LibMaterial := TGLMaterialLibrary(Layout.Material.MaterialLibrary)
  765. .Materials.GetLibMaterialByName(Layout.Material.LibMaterialName);
  766. if Assigned(LibMaterial) then
  767. Material := LibMaterial.Material;
  768. end;
  769. if not Assigned(Material) then
  770. begin
  771. Material := Layout.Material;
  772. end;
  773. if Refresh then
  774. begin
  775. Res[GLAlTopLeft].X1 := X1;
  776. Res[GLAlTopLeft].Y1 := Y1;
  777. Res[GLAlTopLeft].X2 := X1;
  778. Res[GLAlTopLeft].Y2 := Y1;
  779. Res[GLAlTopRight].X1 := X2;
  780. Res[GLAlTopRight].Y1 := Y1;
  781. Res[GLAlTopRight].X2 := X2;
  782. Res[GLAlTopRight].Y2 := Y1;
  783. Res[GLAlBottomLeft].X1 := X1;
  784. Res[GLAlBottomLeft].Y1 := Y2;
  785. Res[GLAlBottomLeft].X2 := X1;
  786. Res[GLAlBottomLeft].Y2 := Y2;
  787. Res[GLAlBottomRight].X1 := X2;
  788. Res[GLAlBottomRight].Y1 := Y2;
  789. Res[GLAlBottomRight].X2 := X2;
  790. Res[GLAlBottomRight].Y2 := Y2;
  791. for xc := 0 to FElements.Count - 1 do
  792. begin
  793. ThisElement := FElements[xc];
  794. if GLAlBorder = ThisElement.Align then
  795. begin
  796. Res[GLAlTopLeft].X1 := X1;
  797. Res[GLAlTopLeft].Y1 := Y1;
  798. Res[GLAlTopLeft].X2 := X1 + ThisElement.Scale.X * Scale *
  799. ThisElement.Scale.Z;
  800. Res[GLAlTopLeft].Y2 := Y1 + ThisElement.Scale.Y * Scale *
  801. ThisElement.Scale.Z;
  802. Res[GLAlTop].X1 := X1 + ThisElement.Scale.X * Scale *
  803. ThisElement.Scale.Z;
  804. Res[GLAlTop].Y1 := Y1;
  805. Res[GLAlTop].X2 := X2 - ThisElement.Scale.X * Scale *
  806. ThisElement.Scale.Z;
  807. Res[GLAlTop].Y2 := Y1 + ThisElement.Scale.Y * Scale *
  808. ThisElement.Scale.Z;
  809. Res[GLAlTopRight].X1 := X2 - ThisElement.Scale.X * Scale *
  810. ThisElement.Scale.Z;
  811. Res[GLAlTopRight].Y1 := Y1;
  812. Res[GLAlTopRight].X2 := X2;
  813. Res[GLAlTopRight].Y2 := Y1 + ThisElement.Scale.Y * Scale *
  814. ThisElement.Scale.Z;
  815. Res[GLAlRight].X1 := X2 - ThisElement.Scale.X * Scale *
  816. ThisElement.Scale.Z;
  817. Res[GLAlRight].Y1 := Y1 + ThisElement.Scale.Y * Scale *
  818. ThisElement.Scale.Z;
  819. Res[GLAlRight].X2 := X2;
  820. Res[GLAlRight].Y2 := Y2 - ThisElement.Scale.Y * Scale *
  821. ThisElement.Scale.Z;
  822. Res[GLAlBottomRight].X1 := X2 - ThisElement.Scale.X * Scale *
  823. ThisElement.Scale.Z;
  824. Res[GLAlBottomRight].Y1 := Y2 - ThisElement.Scale.Y * Scale *
  825. ThisElement.Scale.Z;
  826. Res[GLAlBottomRight].X2 := X2;
  827. Res[GLAlBottomRight].Y2 := Y2;
  828. Res[GLAlBottom].X1 := X1 + ThisElement.Scale.X * Scale *
  829. ThisElement.Scale.Z;
  830. Res[GLAlBottom].Y1 := Y2 - ThisElement.Scale.Y * Scale *
  831. ThisElement.Scale.Z;
  832. Res[GLAlBottom].X2 := X2 - ThisElement.Scale.X * Scale *
  833. ThisElement.Scale.Z;
  834. Res[GLAlBottom].Y2 := Y2;
  835. Res[GLAlBottomLeft].X1 := X1;
  836. Res[GLAlBottomLeft].Y1 := Y2 - ThisElement.Scale.Y * Scale *
  837. ThisElement.Scale.Z;
  838. Res[GLAlBottomLeft].X2 := X1 + ThisElement.Scale.X * Scale *
  839. ThisElement.Scale.Z;
  840. Res[GLAlBottomLeft].Y2 := Y2;
  841. Res[GLAlLeft].X1 := X1;
  842. Res[GLAlLeft].Y1 := Y1 + ThisElement.Scale.Y * Scale *
  843. ThisElement.Scale.Z;
  844. Res[GLAlLeft].X2 := X1 + ThisElement.Scale.X * Scale *
  845. ThisElement.Scale.Z;
  846. Res[GLAlLeft].Y2 := Y2 - ThisElement.Scale.Y * Scale *
  847. ThisElement.Scale.Z;
  848. Res[GLAlCenter].X1 := X1 + ThisElement.Scale.X * Scale *
  849. ThisElement.Scale.Z;
  850. Res[GLAlCenter].Y1 := Y1 + ThisElement.Scale.Y * Scale *
  851. ThisElement.Scale.Z;
  852. Res[GLAlCenter].X2 := X2 - ThisElement.Scale.X * Scale *
  853. ThisElement.Scale.Z;
  854. Res[GLAlCenter].Y2 := Y2 - ThisElement.Scale.Y * Scale *
  855. ThisElement.Scale.Z;
  856. end;
  857. if GLAlTopLeft = ThisElement.Align then
  858. begin
  859. Prepare;
  860. Res[GLAlTopLeft].X1 := X1;
  861. Res[GLAlTopLeft].Y1 := Y1;
  862. Res[GLAlTopLeft].X2 := X1 + W;
  863. Res[GLAlTopLeft].Y2 := Y1 + H;
  864. end;
  865. if GLAlTopRight = ThisElement.Align then
  866. begin
  867. Prepare;
  868. Res[GLAlTopRight].X1 := X2 - W;
  869. Res[GLAlTopRight].Y1 := Y1;
  870. Res[GLAlTopRight].X2 := X2;
  871. Res[GLAlTopRight].Y2 := Y1 + H;
  872. end;
  873. if GLAlBottomLeft = ThisElement.Align then
  874. begin
  875. Prepare;
  876. Res[GLAlBottomLeft].X1 := X1;
  877. Res[GLAlBottomLeft].Y1 := Y2 - H;
  878. Res[GLAlBottomLeft].X2 := X1 + W;
  879. Res[GLAlBottomLeft].Y2 := Y2;
  880. end;
  881. if GLAlBottomRight = ThisElement.Align then
  882. begin
  883. Prepare;
  884. Res[GLAlBottomRight].X1 := X2 - W;
  885. Res[GLAlBottomRight].Y1 := Y2 - H;
  886. Res[GLAlBottomRight].X2 := X2;
  887. Res[GLAlBottomRight].Y2 := Y2;
  888. end;
  889. end;
  890. Res[GLAlTop].X1 := Res[GLAlTopLeft].X2;
  891. Res[GLAlTop].Y1 := Res[GLAlTopRight].Y1;
  892. Res[GLAlTop].X2 := Res[GLAlTopRight].X1;
  893. Res[GLAlTop].Y2 := Res[GLAlTopLeft].Y2;
  894. Res[GLAlBottom].X1 := Res[GLAlBottomLeft].X2;
  895. Res[GLAlBottom].Y1 := Res[GLAlBottomLeft].Y1;
  896. Res[GLAlBottom].X2 := Res[GLAlBottomRight].X1;
  897. Res[GLAlBottom].Y2 := Res[GLAlBottomRight].Y2;
  898. Res[GLAlLeft].X1 := Res[GLAlTopLeft].X1;
  899. Res[GLAlLeft].Y1 := Res[GLAlTopLeft].Y2;
  900. Res[GLAlLeft].X2 := Res[GLAlBottomLeft].X2;
  901. Res[GLAlLeft].Y2 := Res[GLAlBottomLeft].Y1;
  902. Res[GLAlRight].X1 := Res[GLAlTopRight].X1;
  903. Res[GLAlRight].Y1 := Res[GLAlTopRight].Y2;
  904. Res[GLAlRight].X2 := Res[GLAlBottomRight].X2;
  905. Res[GLAlRight].Y2 := Res[GLAlBottomRight].Y1;
  906. for xc := 0 to FElements.Count - 1 do
  907. begin
  908. ThisElement := FElements[xc];
  909. if GLAlTop = ThisElement.Align then
  910. begin
  911. Prepare;
  912. Res[GLAlTop].Y1 := Y1;
  913. Res[GLAlTop].Y2 := Y1 + H;
  914. end;
  915. if GLAlBottom = ThisElement.Align then
  916. begin
  917. Prepare;
  918. Res[GLAlBottom].Y1 := Y2 - H;
  919. Res[GLAlBottom].Y2 := Y2;
  920. end;
  921. if GLAlLeft = ThisElement.Align then
  922. begin
  923. Prepare;
  924. Res[GLAlLeft].X1 := X1;
  925. Res[GLAlLeft].X2 := X1 + W;
  926. end;
  927. if GLAlRight = ThisElement.Align then
  928. begin
  929. Prepare;
  930. Res[GLAlRight].X1 := X2 - W;
  931. Res[GLAlRight].X2 := X2;
  932. end;
  933. end;
  934. Res[GLAlCenter].X1 := Res[GLAlLeft].X2;
  935. Res[GLAlCenter].Y1 := Res[GLAlTop].Y2;
  936. Res[GLAlCenter].X2 := Res[GLAlRight].X1;
  937. Res[GLAlCenter].Y2 := Res[GLAlBottom].Y1;
  938. end;
  939. TexWidth := Material.Texture.TexWidth;
  940. if TexWidth = 0 then
  941. TexWidth := Material.Texture.Image.Width;
  942. TexHeight := Material.Texture.TexHeight;
  943. if TexHeight = 0 then
  944. TexHeight := Material.Texture.Image.Height;
  945. gl.Begin_(GL_QUADS);
  946. for xc := 0 to FElements.Count - 1 do
  947. begin
  948. ThisElement := FElements[xc];
  949. for AlignCount := GLAlTopLeft to GLAlBottomRight do
  950. if (AlignCount = ThisElement.Align) then
  951. begin
  952. if Refresh then
  953. begin
  954. Res[AlignCount].XTiles := ((Res[AlignCount].X2 - Res[AlignCount].X1) /
  955. (ThisElement.FBottomRight.X - ThisElement.FTopLeft.X)) /
  956. ThisElement.Scale.X;
  957. Res[AlignCount].YTiles := ((Res[AlignCount].Y2 - Res[AlignCount].Y1) /
  958. (ThisElement.FBottomRight.Y - ThisElement.FTopLeft.Y)) /
  959. ThisElement.Scale.Y;
  960. end;
  961. RenderIt(Res[AlignCount], ThisElement);
  962. end;
  963. if (GLAlBorder = ThisElement.Align) then
  964. begin
  965. RenderBorder(ThisElement);
  966. end;
  967. end;
  968. gl.End_;
  969. end;
  970. function TGLGuiComponent.GetOwnerList: TGLGuiComponentList;
  971. begin
  972. Result := GetOwner as TGLGuiComponentList;
  973. end;
  974. function TGLGuiComponent.GetDisplayName: string;
  975. begin
  976. Result := FName;
  977. end;
  978. procedure TGLGuiComponent.SetName(const val: TGLGuiComponentName);
  979. begin
  980. FName := val;
  981. end;
  982. constructor TGLGuiComponent.Create(Collection: TCollection);
  983. begin
  984. inherited;
  985. FElements := TGLGuiElementList.Create(Self);
  986. end;
  987. destructor TGLGuiComponent.Destroy;
  988. begin
  989. FElements.Free;
  990. inherited;
  991. end;
  992. constructor TGLGuiElementList.Create(AOwner: TGLGuiComponent);
  993. begin
  994. inherited Create(AOwner, TGLGuiElement);
  995. FGuiComponent := AOwner;
  996. end;
  997. function TGLGuiElementList.GetOwner: TPersistent;
  998. begin
  999. Result := FGuiComponent;
  1000. end;
  1001. procedure TGLGuiElementList.SetItems(index: Integer; const val: TGLGuiElement);
  1002. begin
  1003. inherited Items[index] := val;
  1004. end;
  1005. function TGLGuiElementList.IndexOf(const Item: TGLGuiElement): Integer;
  1006. var
  1007. i: Integer;
  1008. begin
  1009. Result := -1;
  1010. if Count <> 0 then
  1011. for i := 0 to Count - 1 do
  1012. if GetItems(i) = Item then
  1013. begin
  1014. Result := i;
  1015. Exit;
  1016. end;
  1017. end;
  1018. function TGLGuiElementList.GetItems(index: Integer): TGLGuiElement;
  1019. begin
  1020. Result := TGLGuiElement(inherited Items[index]);
  1021. end;
  1022. function TGLGuiElement.GetDisplayName: string;
  1023. begin
  1024. Result := FName;
  1025. end;
  1026. procedure TGLGuiElement.SetName(const val: TGLGuiElementName);
  1027. begin
  1028. FName := val;
  1029. end;
  1030. constructor TGLGuiElement.Create(Collection: TCollection);
  1031. begin
  1032. inherited;
  1033. FTopLeft := TGLCoordinates2.CreateInitialized(Self, NullHmgVector, csPoint2D);
  1034. FBottomRight := TGLCoordinates2.CreateInitialized(Self, NullHmgVector,
  1035. csPoint2D);
  1036. FScale := TGLCoordinates2.CreateInitialized(Self, XYHmgVector, csPoint2D);
  1037. end;
  1038. destructor TGLGuiElement.Destroy;
  1039. begin
  1040. FTopLeft.Free;
  1041. FBottomRight.Free;
  1042. FScale.Free;
  1043. inherited;
  1044. end;
  1045. procedure TGLGuiLayout.Notification(AComponent: TComponent;
  1046. Operation: TOperation);
  1047. begin
  1048. if Operation = opRemove then
  1049. begin
  1050. if AComponent = FBitmapFont then
  1051. BitmapFont := nil
  1052. else
  1053. FGuiComponentList.Remove(AComponent);
  1054. end;
  1055. NotifyChange(Self); // EG : looks suspicious...
  1056. inherited;
  1057. end;
  1058. procedure TGLGuiComponent.AssignTo(Dest: TPersistent);
  1059. begin
  1060. if Dest is TGLGuiComponent then
  1061. begin
  1062. TGLGuiComponent(Dest).Elements.Assign(Elements);
  1063. end
  1064. else
  1065. inherited;
  1066. end;
  1067. procedure TGLGuiElementList.AssignTo(Dest: TPersistent);
  1068. var
  1069. i: Integer;
  1070. begin
  1071. if Dest is TGLGuiElementList then
  1072. begin
  1073. for i := 0 to Count - 1 do
  1074. begin
  1075. TGLGuiElementList(Dest).Add.Assign(Items[i]);
  1076. end;
  1077. end
  1078. else
  1079. inherited;
  1080. end;
  1081. procedure TGLGuiElement.AssignTo(Dest: TPersistent);
  1082. var
  1083. element: TGLGuiElement;
  1084. begin
  1085. if Dest is TGLGuiElement then
  1086. begin
  1087. element := TGLGuiElement(Dest);
  1088. element.TopLeft.Assign(TopLeft);
  1089. element.BottomRight.Assign(BottomRight);
  1090. element.Scale.Assign(Scale);
  1091. element.Align := Align;
  1092. element.name := Name;
  1093. end
  1094. else
  1095. inherited;
  1096. end;
  1097. end.