GLS.Gui.pas 33 KB

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