123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- unit GBE.Clouds;
- interface
- uses
- System.SysUtils,
- System.Classes,
- System.Generics.Collections,
- System.Math.Vectors,
- System.Threading,
- FMX.Types,
- FMX.Types3D,
- FMX.Controls3D,
- FMX.Objects3D,
- FMX.MaterialSources;
- type
- TGBEClouds = class(TDummy)
- private
- fListClouds: TList<TPlane>;
- fNbClouds, fLimits: integer;
- fWindSpeed: single;
- fActiveWind, fUseTasks: boolean;
- fTexturesClouds: TList<TTextureMaterialSource>;
- function GetNbClouds: integer;
- function GetWindSpeed: single;
- procedure SetNbClouds(const Value: integer);
- procedure SetWindSpeed(const Value: single);
- function GetLimits: integer;
- procedure SetLimits(const Value: integer);
- function GetActiveWind: boolean;
- procedure SetActiveWind(const Value: boolean);
- procedure DeplacementNuages;
- protected
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure DeleteTexturesClouds;
- procedure AddTextureCloud(TextureMaterial: TTextureMaterialSource);
- procedure MoveClouds;
- procedure GenerateClouds;
- published
- property ActiveWind: boolean read GetActiveWind write SetActiveWind;
- property Limits: integer read GetLimits write SetLimits;
- property NbClouds: integer read GetNbClouds write SetNbClouds;
- property WindSpeed: single read GetWindSpeed write SetWindSpeed;
- property UseTasks: boolean read fUseTasks write fUseTasks;
- end;
- procedure Register;
- implementation // --------------------------------------------------------------
- // TGBEClouds
- procedure TGBEClouds.AddTextureCloud(TextureMaterial: TTextureMaterialSource);
- begin
- fTexturesClouds.Add(TextureMaterial);
- end;
- constructor TGBEClouds.Create(AOwner: TComponent);
- begin
- inherited;
- hitTest := false;
- fLimits := 200;
- fWindSpeed := 0.5;
- fNbClouds := 0;
- fActiveWind := false;
- fListClouds := TList<TPlane>.Create;
- fTexturesClouds := TList<TTextureMaterialSource>.Create;
- fUseTasks := true;
- end;
- procedure TGBEClouds.DeleteTexturesClouds;
- begin
- if fTexturesClouds.Count > 0 then
- fTexturesClouds.Clear;
- end;
- destructor TGBEClouds.Destroy;
- begin
- fListClouds.Free;
- fTexturesClouds.Free;
- DoDeleteChildren;
- inherited;
- end;
- function TGBEClouds.GetActiveWind: boolean;
- begin
- Result := fActiveWind;
- end;
- function TGBEClouds.GetLimits: integer;
- begin
- Result := fLimits;
- end;
- function TGBEClouds.GetNbClouds: integer;
- begin
- Result := fNbClouds;
- end;
- function TGBEClouds.GetWindSpeed: single;
- begin
- Result := fWindSpeed;
- end;
- procedure TGBEClouds.MoveClouds;
- begin
- if (fActiveWind) and (NbClouds > 0) then
- begin
- if fUseTasks then
- begin
- TTask.Create(
- procedure
- begin
- DeplacementNuages;
- end).start;
- end
- else
- begin
- DeplacementNuages;
- end;
- end;
- end;
- procedure TGBEClouds.DeplacementNuages;
- var
- s: TPlane;
- P: TFmxObject;
- // Will serve as an iterator to traverse all child objects of dmyNuages
- begin
- for P in self.Children do // Traversing the child objects of dmyNuages
- begin
- if P is TPlane then // If the object is a TPlane
- begin
- s := TPlane(P); // We will work on this TPlane
- s.position.x := s.position.x + fWindSpeed / (s.position.z);
- if (s.position.x > fLimits) or (s.position.x < -fLimits) then
- // If the X position of the cloud > 1000,
- // then we reposition the cloud at position x = -1000 and Y and Z random values
- begin
- s.position.point := Point3D(-fLimits, random - 0.5,
- random * fLimits * (0.5 - random));
- s.Opacity := random;
- end;
- end;
- end;
- end;
- procedure TGBEClouds.SetActiveWind(const Value: boolean);
- begin
- if Value <> fActiveWind then
- fActiveWind := Value;
- end;
- procedure TGBEClouds.SetLimits(const Value: integer);
- begin
- if Value <> fLimits then
- begin
- fLimits := Value;
- end;
- end;
- procedure TGBEClouds.SetNbClouds(const Value: integer);
- begin
- if Value <> fNbClouds then
- begin
- fNbClouds := Value;
- GenerateClouds;
- end;
- end;
- procedure TGBEClouds.SetWindSpeed(const Value: single);
- begin
- if Value <> fWindSpeed then
- fWindSpeed := Value;
- end;
- procedure TGBEClouds.GenerateClouds;
- var
- s: TPlane;
- taille: integer;
- i, nbTextures: integer;
- begin
- self.DeleteChildren;
- fListClouds.Clear;
- Randomize;
- nbTextures := fTexturesClouds.Count;
- for i := 0 to NbClouds - 1 do
- begin
- s := TPlane.Create(nil);
- s.parent := self;
- taille := random(fLimits);
- s.MaterialSource := fTexturesClouds[random(nbTextures) mod nbTextures];
- s.SetSize(taille, taille * 0.5, 0.001);
- s.TwoSide := true;
- // To make the texture apply to both sides of the TPlane
- s.RotationAngle.x := -90; // To orient the TPlanes parallel to the ground
- s.Opacity := random(); // Random opacity to improve rendering
- s.Opaque := false;
- s.ZWrite := false;
- // to avoid the TPlane "frame" rectangle being visible =>
- // but then the depth is no longer managed: the Sun passes in front of the clouds...
- s.hitTest := false; // so you can't click on it
- s.tag := self.tag;
- s.position.point := Point3D(random() * fLimits * (0.5 - Random()),
- Random() - 0.5, Random() * fLimits * (0.5 - Random()));
- // We position the cloud arbitrarily and randomly everywhere above our world
- s.RotationAngle.z := Random() * 360; // Random cloud orientation
- end;
- end;
- procedure Register;
- begin
- RegisterComponents('GXScene GBE', [TGBEClouds]);
- end;
- end.
|