GBE.Clouds.pas 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. unit GBE.Clouds;
  2. interface
  3. uses
  4. System.SysUtils,
  5. System.Classes,
  6. System.Generics.Collections,
  7. System.Math.Vectors,
  8. System.Threading,
  9. FMX.Types,
  10. FMX.Types3D,
  11. FMX.Controls3D,
  12. FMX.Objects3D,
  13. FMX.MaterialSources;
  14. type
  15. TGBEClouds = class(TDummy)
  16. private
  17. fListClouds: TList<TPlane>;
  18. fNbClouds, fLimits: integer;
  19. fWindSpeed: single;
  20. fActiveWind, fUseTasks: boolean;
  21. fTexturesClouds: TList<TTextureMaterialSource>;
  22. function GetNbClouds: integer;
  23. function GetWindSpeed: single;
  24. procedure SetNbClouds(const Value: integer);
  25. procedure SetWindSpeed(const Value: single);
  26. function GetLimits: integer;
  27. procedure SetLimits(const Value: integer);
  28. function GetActiveWind: boolean;
  29. procedure SetActiveWind(const Value: boolean);
  30. procedure DeplacementNuages;
  31. protected
  32. public
  33. constructor Create(AOwner: TComponent); override;
  34. destructor Destroy; override;
  35. procedure DeleteTexturesClouds;
  36. procedure AddTextureCloud(TextureMaterial: TTextureMaterialSource);
  37. procedure MoveClouds;
  38. procedure GenerateClouds;
  39. published
  40. property ActiveWind: boolean read GetActiveWind write SetActiveWind;
  41. property Limits: integer read GetLimits write SetLimits;
  42. property NbClouds: integer read GetNbClouds write SetNbClouds;
  43. property WindSpeed: single read GetWindSpeed write SetWindSpeed;
  44. property UseTasks: boolean read fUseTasks write fUseTasks;
  45. end;
  46. procedure Register;
  47. implementation // --------------------------------------------------------------
  48. // TGBEClouds
  49. procedure TGBEClouds.AddTextureCloud(TextureMaterial: TTextureMaterialSource);
  50. begin
  51. fTexturesClouds.Add(TextureMaterial);
  52. end;
  53. constructor TGBEClouds.Create(AOwner: TComponent);
  54. begin
  55. inherited;
  56. hitTest := false;
  57. fLimits := 200;
  58. fWindSpeed := 0.5;
  59. fNbClouds := 0;
  60. fActiveWind := false;
  61. fListClouds := TList<TPlane>.Create;
  62. fTexturesClouds := TList<TTextureMaterialSource>.Create;
  63. fUseTasks := true;
  64. end;
  65. procedure TGBEClouds.DeleteTexturesClouds;
  66. begin
  67. if fTexturesClouds.Count > 0 then
  68. fTexturesClouds.Clear;
  69. end;
  70. destructor TGBEClouds.Destroy;
  71. begin
  72. fListClouds.Free;
  73. fTexturesClouds.Free;
  74. DoDeleteChildren;
  75. inherited;
  76. end;
  77. function TGBEClouds.GetActiveWind: boolean;
  78. begin
  79. Result := fActiveWind;
  80. end;
  81. function TGBEClouds.GetLimits: integer;
  82. begin
  83. Result := fLimits;
  84. end;
  85. function TGBEClouds.GetNbClouds: integer;
  86. begin
  87. Result := fNbClouds;
  88. end;
  89. function TGBEClouds.GetWindSpeed: single;
  90. begin
  91. Result := fWindSpeed;
  92. end;
  93. procedure TGBEClouds.MoveClouds;
  94. begin
  95. if (fActiveWind) and (NbClouds > 0) then
  96. begin
  97. if fUseTasks then
  98. begin
  99. TTask.Create(
  100. procedure
  101. begin
  102. DeplacementNuages;
  103. end).start;
  104. end
  105. else
  106. begin
  107. DeplacementNuages;
  108. end;
  109. end;
  110. end;
  111. procedure TGBEClouds.DeplacementNuages;
  112. var
  113. s: TPlane;
  114. P: TFmxObject;
  115. // Will serve as an iterator to traverse all child objects of dmyNuages
  116. begin
  117. for P in self.Children do // Traversing the child objects of dmyNuages
  118. begin
  119. if P is TPlane then // If the object is a TPlane
  120. begin
  121. s := TPlane(P); // We will work on this TPlane
  122. s.position.x := s.position.x + fWindSpeed / (s.position.z);
  123. if (s.position.x > fLimits) or (s.position.x < -fLimits) then
  124. // If the X position of the cloud > 1000,
  125. // then we reposition the cloud at position x = -1000 and Y and Z random values
  126. begin
  127. s.position.point := Point3D(-fLimits, random - 0.5,
  128. random * fLimits * (0.5 - random));
  129. s.Opacity := random;
  130. end;
  131. end;
  132. end;
  133. end;
  134. procedure TGBEClouds.SetActiveWind(const Value: boolean);
  135. begin
  136. if Value <> fActiveWind then
  137. fActiveWind := Value;
  138. end;
  139. procedure TGBEClouds.SetLimits(const Value: integer);
  140. begin
  141. if Value <> fLimits then
  142. begin
  143. fLimits := Value;
  144. end;
  145. end;
  146. procedure TGBEClouds.SetNbClouds(const Value: integer);
  147. begin
  148. if Value <> fNbClouds then
  149. begin
  150. fNbClouds := Value;
  151. GenerateClouds;
  152. end;
  153. end;
  154. procedure TGBEClouds.SetWindSpeed(const Value: single);
  155. begin
  156. if Value <> fWindSpeed then
  157. fWindSpeed := Value;
  158. end;
  159. procedure TGBEClouds.GenerateClouds;
  160. var
  161. s: TPlane;
  162. taille: integer;
  163. i, nbTextures: integer;
  164. begin
  165. self.DeleteChildren;
  166. fListClouds.Clear;
  167. Randomize;
  168. nbTextures := fTexturesClouds.Count;
  169. for i := 0 to NbClouds - 1 do
  170. begin
  171. s := TPlane.Create(nil);
  172. s.parent := self;
  173. taille := random(fLimits);
  174. s.MaterialSource := fTexturesClouds[random(nbTextures) mod nbTextures];
  175. s.SetSize(taille, taille * 0.5, 0.001);
  176. s.TwoSide := true;
  177. // To make the texture apply to both sides of the TPlane
  178. s.RotationAngle.x := -90; // To orient the TPlanes parallel to the ground
  179. s.Opacity := random(); // Random opacity to improve rendering
  180. s.Opaque := false;
  181. s.ZWrite := false;
  182. // to avoid the TPlane "frame" rectangle being visible =>
  183. // but then the depth is no longer managed: the Sun passes in front of the clouds...
  184. s.hitTest := false; // so you can't click on it
  185. s.tag := self.tag;
  186. s.position.point := Point3D(random() * fLimits * (0.5 - Random()),
  187. Random() - 0.5, Random() * fLimits * (0.5 - Random()));
  188. // We position the cloud arbitrarily and randomly everywhere above our world
  189. s.RotationAngle.z := Random() * 360; // Random cloud orientation
  190. end;
  191. end;
  192. procedure Register;
  193. begin
  194. RegisterComponents('GXScene GBE', [TGBEClouds]);
  195. end;
  196. end.