LZScene

Форк
0
/
GLBehaviours.pas 
761 строка · 21.2 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
  Standard TGLBehaviour subclasses for GLScene
6

7
   History :  
8
     08/05/08 - DaStr - Added a global GetInertia() function
9
     19/12/06 - DaStr - TGLBAcceleration.Create - creates Inertia right away,
10
                         thus displaying it in the XCollection Editor
11
                         TGLBAcceleration.DoProgress - raises an exception
12
                         when required Inertia component is deleted by user
13
     24/09/02 - Egg - Support for negative rotation speeds (Marco Chong)
14
     02/10/00 - Egg - Fixed TGLBInertia.DoProgress (DamplingEnabled bug)
15
     09/10/00 - Egg - Fixed ApplyTranslationAcceleration & ApplyForce
16
     11/08/00 - Egg - Fixed translation bug with root level objects & Inertia
17
     10/04/00 - Egg - Improved persistence logic
18
     06/04/00 - Egg - Added Damping stuff to inertia
19
     05/04/00 - Egg - Creation
20
   
21
}
22
unit GLBehaviours;
23

24
interface
25

26
{$I GLScene.inc}
27

28
uses
29
  Classes, SysUtils,
30
  GLVectorTypes,
31
  GLScene,
32
  GLVectorGeometry,
33
  GLXCollection,
34
  GLBaseClasses,
35
  GLCoordinates;
36

37
type
38

39
  // TGLDamping
40

41
  { Holds parameters for TGLScene basic damping model.
42
    Damping is modeled by calculating a force from the speed, this force
43
    can then be transformed to an acceleration is you know the object's mass. 
44
    Formulas : 
45
     damping = constant + linear * Speed + quadratic * Speed^2
46
     accel = damping / Mass
47
      That's just basic physics :). A note on the components : 
48
     constant : use it for solid friction (will stop abruptly an object after
49
      decreasing its speed.
50
     linear : linear friction damping.
51
     quadratic : expresses viscosity.
52
       }
53
  TGLDamping = class(TGLUpdateAbleObject)
54
  private
55
     
56
    FConstant: single;
57
    FLinear: single;
58
    FQuadratic: single;
59

60
  protected
61
     
62

63
  public
64
     
65
    constructor Create(aOwner: TPersistent); override;
66
    destructor Destroy; override;
67

68
    procedure WriteToFiler(writer: TWriter);
69
    procedure ReadFromFiler(reader: TReader);
70

71
    procedure Assign(Source: TPersistent); override;
72
      { Calculates attenuated speed over deltaTime.
73
            Integration step is 0.01 sec, and the following formula is applied
74
            at each step: constant+linear*speed+quadratic*speed^2 }
75
    function Calculate(speed, deltaTime: double): double;
76
    // Returns a "[constant; linear; quadractic]" string
77
    function AsString(const damping: TGLDamping): string;
78
    { Sets all damping parameters in a single call. }
79
    procedure SetDamping(const constant: single = 0; const linear: single = 0;
80
      const quadratic: single = 0);
81

82
  published
83
     
84
    property Constant: single read FConstant write FConstant;
85
    property Linear: single read FLinear write FLinear;
86
    property Quadratic: single read FQuadratic write FQuadratic;
87
  end;
88

89
  // TGLBInertia
90

91
  { Simple translation and rotation Inertia behaviour.
92
    Stores translation and rotation speeds, to which you can apply
93
    accelerations.
94
    Note that the rotation model is not physical, so feel free to contribute
95
    a "realworld" inertia class with realistic, axis-free, rotation inertia
96
    if this approximation does not suits your needs :). }
97
  TGLBInertia = class(TGLBehaviour)
98
  private
99
     
100
    FMass: single;
101
    FTranslationSpeed: TGLCoordinates;
102
    FTurnSpeed, FRollSpeed, FPitchSpeed: single;
103
    FTranslationDamping, FRotationDamping: TGLDamping;
104
    FDampingEnabled: boolean;
105

106
  protected
107
     
108
    procedure SetTranslationSpeed(const val: TGLCoordinates);
109
    procedure SetTranslationDamping(const val: TGLDamping);
110
    procedure SetRotationDamping(const val: TGLDamping);
111

112
    procedure WriteToFiler(writer: TWriter); override;
113
    procedure ReadFromFiler(reader: TReader); override;
114

115
  public
116
     
117
    constructor Create(aOwner: TGLXCollection); override;
118
    destructor Destroy; override;
119

120
    procedure Assign(Source: TPersistent); override;
121

122
    class function FriendlyName: string; override;
123
    class function FriendlyDescription: string; override;
124
    class function UniqueItem: boolean; override;
125

126
    procedure DoProgress(const progressTime: TProgressTimes); override;
127

128
    { Adds time-proportionned acceleration to the speed. }
129
    procedure ApplyTranslationAcceleration(const deltaTime: double;
130
      const accel: TVector);
131
      { Applies a timed force to the inertia.
132
        If Mass is null, nothing is done. }
133
    procedure ApplyForce(const deltaTime: double; const force: TVector);
134
      { Applies a timed torque to the inertia (yuck!).
135
        This gets a "yuck!" because it is as false as the rest of the
136
        rotation  model. }
137
    procedure ApplyTorque(const deltaTime: double;
138
      const turnTorque, rollTorque, pitchTorque: single);
139
    { Inverts the translation vector. }
140
    procedure MirrorTranslation;
141
         { Bounce speed as if hitting a surface.
142
            restitution is the coefficient of restituted energy (1=no energy loss,
143
            0=no bounce). The normal is NOT assumed to be normalized. }
144
    procedure SurfaceBounce(const surfaceNormal: TVector; restitution: single);
145

146
  published
147
     
148
    property Mass: single read FMass write FMass;
149
    property TranslationSpeed: TGLCoordinates
150
      read FTranslationSpeed write SetTranslationSpeed;
151
    property TurnSpeed: single read FTurnSpeed write FTurnSpeed;
152
    property RollSpeed: single read FRollSpeed write FRollSpeed;
153
    property PitchSpeed: single read FPitchSpeed write FPitchSpeed;
154

155
      { Enable/Disable damping (damping has a high cpu-cycle cost).
156
        Damping is enabled by default. }
157
    property DampingEnabled: boolean read FDampingEnabled write FDampingEnabled;
158
      { Damping applied to translation speed. 
159
        Note that it is not "exactly" applied, ie. if damping would stop
160
        your object after 0.5 time unit, and your progression steps are
161
        of 1 time unit, there will be an integration error of 0.5 time unit. }
162
    property TranslationDamping: TGLDamping read FTranslationDamping
163
      write SetTranslationDamping;
164
      { Damping applied to rotation speed (yuck!). 
165
        Well, this one is not "exact", like TranslationDamping, and neither
166
        it is "physical" since I'm reusing the mass and... and... well don't
167
        show this to your science teacher 8). 
168
        Anyway that's easier to use than the realworld formulas, calculated
169
        faster, and properly used can give a good illusion of reality. }
170
    property RotationDamping: TGLDamping read FRotationDamping write SetRotationDamping;
171
  end;
172

173
  // TGLBAcceleration
174

175
  { Applies a constant acceleration to a TGLBInertia. }
176
  TGLBAcceleration = class(TGLBehaviour)
177
  private
178
     
179
    FAcceleration: TGLCoordinates;
180

181
  protected
182
     
183
    procedure SetAcceleration(const val: TGLCoordinates);
184

185
    procedure WriteToFiler(writer: TWriter); override;
186
    procedure ReadFromFiler(reader: TReader); override;
187

188
  public
189
     
190
    constructor Create(aOwner: TGLXCollection); override;
191
    destructor Destroy; override;
192

193
    procedure Assign(Source: TPersistent); override;
194

195
    class function FriendlyName: string; override;
196
    class function FriendlyDescription: string; override;
197
    class function UniqueItem: boolean; override;
198

199
    procedure DoProgress(const progressTime: TProgressTimes); override;
200

201
  published
202
     
203
    property Acceleration: TGLCoordinates read FAcceleration write FAcceleration;
204
  end;
205

206
{ Returns or creates the TGLBInertia within the given behaviours.
207
  This helper function is convenient way to access a TGLBInertia. }
208
function GetInertia(const AGLSceneObject: TGLBaseSceneObject): TGLBInertia;
209
function GetOrCreateInertia(behaviours: TGLBehaviours): TGLBInertia; overload;
210
function GetOrCreateInertia(obj: TGLBaseSceneObject): TGLBInertia; overload;
211

212
{ Returns or creates the TGLBAcceleration within the given behaviours.
213
  This helper function is convenient way to access a TGLBAcceleration. }
214
function GetOrCreateAcceleration(behaviours: TGLBehaviours): TGLBAcceleration;
215
  overload;
216
function GetOrCreateAcceleration(obj: TGLBaseSceneObject): TGLBAcceleration; overload;
217

218
// ------------------------------------------------------------------
219
// ------------------------------------------------------------------
220
// ------------------------------------------------------------------
221
implementation
222
// ------------------------------------------------------------------
223
// ------------------------------------------------------------------
224
// ------------------------------------------------------------------
225

226
// GetInertia
227

228
function GetInertia(const AGLSceneObject: TGLBaseSceneObject): TGLBInertia;
229
var
230
  i: integer;
231
begin
232
  i := AGLSceneObject.behaviours.IndexOfClass(TGLBInertia);
233
  if i >= 0 then
234
    Result := TGLBInertia(AGLSceneObject.behaviours[i])
235
  else
236
    Result := nil;
237
end;
238

239
// GetOrCreateInertia (TGLBehaviours)
240

241
function GetOrCreateInertia(behaviours: TGLBehaviours): TGLBInertia;
242
var
243
  i: integer;
244
begin
245
  i := behaviours.IndexOfClass(TGLBInertia);
246
  if i >= 0 then
247
    Result := TGLBInertia(behaviours[i])
248
  else
249
    Result := TGLBInertia.Create(behaviours);
250
end;
251

252
// GetOrCreateInertia (TGLBaseSceneObject)
253

254
function GetOrCreateInertia(obj: TGLBaseSceneObject): TGLBInertia;
255
begin
256
  Result := GetOrCreateInertia(obj.Behaviours);
257
end;
258

259
// GetOrCreateAcceleration (TGLBehaviours)
260

261
function GetOrCreateAcceleration(behaviours: TGLBehaviours): TGLBAcceleration;
262
var
263
  i: integer;
264
begin
265
  i := behaviours.IndexOfClass(TGLBAcceleration);
266
  if i >= 0 then
267
    Result := TGLBAcceleration(behaviours[i])
268
  else
269
    Result := TGLBAcceleration.Create(behaviours);
270
end;
271

272
// GetOrCreateAcceleration (TGLBaseSceneObject)
273

274
function GetOrCreateAcceleration(obj: TGLBaseSceneObject): TGLBAcceleration;
275
begin
276
  Result := GetOrCreateAcceleration(obj.Behaviours);
277
end;
278

279
// ------------------
280
// ------------------ TGLDamping ------------------
281
// ------------------
282

283
// Create
284

285
constructor TGLDamping.Create(aOwner: TPersistent);
286
begin
287
  inherited Create(AOwner);
288
end;
289

290
destructor TGLDamping.Destroy;
291
begin
292
  inherited Destroy;
293
end;
294

295
 
296

297
procedure TGLDamping.Assign(Source: TPersistent);
298
begin
299
  if Source is TGLDamping then
300
  begin
301
    FConstant := TGLDamping(Source).Constant;
302
    FLinear := TGLDamping(Source).Linear;
303
    FQuadratic := TGLDamping(Source).Quadratic;
304
  end
305
  else
306
    inherited Assign(Source);
307
end;
308

309
// WriteToFiler
310

311
procedure TGLDamping.WriteToFiler(writer: TWriter);
312
var
313
  writeStuff: boolean;
314
begin
315
  with writer do
316
  begin
317
    WriteInteger(0); // Archive Version 0
318
    writeStuff := (FConstant <> 0) or (FLinear <> 0) or (FQuadratic <> 0);
319
    WriteBoolean(writeStuff);
320
    if writeStuff then
321
    begin
322
      WriteFloat(FConstant);
323
      WriteFloat(FLinear);
324
      WriteFloat(FQuadratic);
325
    end;
326
  end;
327
end;
328

329
// ReadFromFiler
330

331
procedure TGLDamping.ReadFromFiler(reader: TReader);
332
begin
333
  with reader do
334
  begin
335
    ReadInteger; // ignore Archive Version
336
    if ReadBoolean then
337
    begin
338
      FConstant := ReadFloat;
339
      FLinear := ReadFloat;
340
      FQuadratic := ReadFloat;
341
    end
342
    else
343
    begin
344
      FConstant := 0;
345
      FLinear := 0;
346
      FQuadratic := 0;
347
    end;
348
  end;
349
end;
350

351
// Calculate
352

353
function TGLDamping.Calculate(speed, deltaTime: double): double;
354
var
355
  dt: double;
356
begin
357
  while deltaTime > 0 do
358
  begin
359
    if deltaTime > 0.01 then
360
    begin
361
      dt := 0.01;
362
      deltaTime := deltaTime - 0.01;
363
    end
364
    else
365
    begin
366
      dt := deltaTime;
367
      deltaTime := 0;
368
    end;
369
    speed := speed - dt * ((FQuadratic * speed + FLinear) * speed + FConstant);
370
  end;
371
  Result := speed;
372
end;
373

374
// DampingAsString
375

376
function TGLDamping.AsString(const damping: TGLDamping): string;
377
begin
378
  Result := Format('[%f; %f; %f]', [Constant, Linear, Quadratic]);
379
end;
380

381
// SetDamping
382

383
procedure TGLDamping.SetDamping(const constant: single = 0;
384
  const linear: single = 0; const quadratic: single = 0);
385
begin
386
  FConstant := constant;
387
  FLinear := linear;
388
  FQuadratic := quadratic;
389
end;
390

391
// ------------------
392
// ------------------ TGLBInertia ------------------
393
// ------------------
394

395
// Create
396

397
constructor TGLBInertia.Create(aOwner: TGLXCollection);
398
begin
399
  inherited Create(aOwner);
400
  FTranslationSpeed := TGLCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
401
  FMass := 1;
402
  FDampingEnabled := True;
403
  FTranslationDamping := TGLDamping.Create(Self);
404
  FRotationDamping := TGLDamping.Create(Self);
405
end;
406

407
// Destroy
408

409
destructor TGLBInertia.Destroy;
410
begin
411
  FRotationDamping.Free;
412
  FTranslationDamping.Free;
413
  FTranslationSpeed.Free;
414
  inherited Destroy;
415
end;
416

417
 
418

419
procedure TGLBInertia.Assign(Source: TPersistent);
420
begin
421
  if Source.ClassType = Self.ClassType then
422
  begin
423
    FMass := TGLBInertia(Source).Mass;
424
    FTranslationSpeed.Assign(TGLBInertia(Source).FTranslationSpeed);
425
    FTurnSpeed := TGLBInertia(Source).TurnSpeed;
426
    FRollSpeed := TGLBInertia(Source).RollSpeed;
427
    FPitchSpeed := TGLBInertia(Source).PitchSpeed;
428
    FDampingEnabled := TGLBInertia(Source).DampingEnabled;
429
    FTranslationDamping.Assign(TGLBInertia(Source).TranslationDamping);
430
    FRotationDamping.Assign(TGLBInertia(Source).RotationDamping);
431
  end;
432
  inherited Assign(Source);
433
end;
434

435
// WriteToFiler
436

437
procedure TGLBInertia.WriteToFiler(writer: TWriter);
438
begin
439
  inherited;
440
  with writer do
441
  begin
442
    WriteInteger(0); // Archive Version 0
443
    WriteFloat(FMass);
444
    FTranslationSpeed.WriteToFiler(writer);
445
    WriteFloat(FTurnSpeed);
446
    WriteFloat(FRollSpeed);
447
    WriteFloat(FPitchSpeed);
448
    WriteBoolean(FDampingEnabled);
449
    FTranslationDamping.WriteToFiler(writer);
450
    FRotationDamping.WriteToFiler(writer);
451
  end;
452
end;
453

454
// ReadFromFiler
455

456
procedure TGLBInertia.ReadFromFiler(reader: TReader);
457
begin
458
  inherited;
459
  with reader do
460
  begin
461
    ReadInteger; // ignore archiveVersion
462
    FMass := ReadFloat;
463
    FTranslationSpeed.ReadFromFiler(reader);
464
    FTurnSpeed := ReadFloat;
465
    FRollSpeed := ReadFloat;
466
    FPitchSpeed := ReadFloat;
467
    FDampingEnabled := ReadBoolean;
468
    FTranslationDamping.ReadFromFiler(reader);
469
    FRotationDamping.ReadFromFiler(reader);
470
  end;
471
end;
472

473
// SetTranslationSpeed
474

475
procedure TGLBInertia.SetTranslationSpeed(const val: TGLCoordinates);
476
begin
477
  FTranslationSpeed.Assign(val);
478
end;
479

480
// SetTranslationDamping
481

482
procedure TGLBInertia.SetTranslationDamping(const val: TGLDamping);
483
begin
484
  FTranslationDamping.Assign(val);
485
end;
486

487
// SetRotationDamping
488

489
procedure TGLBInertia.SetRotationDamping(const val: TGLDamping);
490
begin
491
  FRotationDamping.Assign(val);
492
end;
493

494
 
495

496
class function TGLBInertia.FriendlyName: string;
497
begin
498
  Result := 'Simple Inertia';
499
end;
500

501
// FriendlyDescription
502

503
class function TGLBInertia.FriendlyDescription: string;
504
begin
505
  Result := 'A simple translation and rotation inertia';
506
end;
507

508
// UniqueBehaviour
509

510
class function TGLBInertia.UniqueItem: boolean;
511
begin
512
  Result := True;
513
end;
514

515
// DoProgress
516

517
procedure TGLBInertia.DoProgress(const progressTime: TProgressTimes);
518
var
519
  trnVector: TVector;
520
  speed, newSpeed: double;
521

522
  procedure ApplyRotationDamping(var rotationSpeed: single);
523
  begin
524
    if rotationSpeed > 0 then
525
    begin
526
      rotationSpeed := RotationDamping.Calculate(rotationSpeed, progressTime.deltaTime);
527
      if rotationSpeed <= 0 then
528
        rotationSpeed := 0;
529
    end
530
    else
531
    begin
532
      rotationSpeed := -RotationDamping.Calculate(-rotationSpeed, progressTime.deltaTime);
533
      if rotationSpeed >= 0 then
534
        rotationSpeed := 0;
535
    end;
536
  end;
537

538
begin
539
  // Apply damping to speed
540
  if DampingEnabled then
541
  begin
542
    // Translation damping
543
    speed := TranslationSpeed.VectorLength;
544
    if speed > 0 then
545
    begin
546
      newSpeed := TranslationDamping.Calculate(speed, progressTime.deltaTime);
547
      if newSpeed <= 0 then
548
      begin
549
        trnVector := NullHmgVector;
550
        TranslationSpeed.AsVector := trnVector;
551
      end
552
      else
553
      begin
554
        TranslationSpeed.Scale(newSpeed / Speed);
555
        SetVector(trnVector, TranslationSpeed.AsVector);
556
      end;
557
    end
558
    else
559
      SetVector(trnVector, NullHmgVector);
560
    // Rotation damping (yuck!)
561
    ApplyRotationDamping(FTurnSpeed);
562
    ApplyRotationDamping(FRollSpeed);
563
    ApplyRotationDamping(FPitchSpeed);
564
  end
565
  else
566
    SetVector(trnVector, TranslationSpeed.AsVector);
567
  // Apply speed to object
568
  with OwnerBaseSceneObject do
569
    with progressTime do
570
    begin
571
      Position.AddScaledVector(deltaTime, trnVector);
572
      TurnAngle := TurnAngle + TurnSpeed * deltaTime;
573
      RollAngle := RollAngle + RollSpeed * deltaTime;
574
      PitchAngle := PitchAngle + PitchSpeed * deltaTime;
575
    end;
576
end;
577

578
// ApplyTranslationAcceleration
579

580
procedure TGLBInertia.ApplyTranslationAcceleration(const deltaTime: double;
581
  const accel: TVector);
582
begin
583
  FTranslationSpeed.AsVector := VectorCombine(FTranslationSpeed.AsVector,
584
    accel, 1, deltaTime);
585
end;
586

587
// ApplyForce
588

589
procedure TGLBInertia.ApplyForce(const deltaTime: double; const force: TVector);
590
begin
591
  if Mass <> 0 then
592
    FTranslationSpeed.AsVector :=
593
      VectorCombine(FTranslationSpeed.AsVector, force, 1, deltaTime / Mass);
594
end;
595

596
// ApplyTorque
597

598
procedure TGLBInertia.ApplyTorque(const deltaTime: double;
599
  const turnTorque, rollTorque, pitchTorque: single);
600
var
601
  factor: double;
602
begin
603
  if Mass <> 0 then
604
  begin
605
    factor := deltaTime / Mass;
606
    FTurnSpeed := FTurnSpeed + turnTorque * factor;
607
    FRollSpeed := FRollSpeed + rollTorque * factor;
608
    FPitchSpeed := FPitchSpeed + pitchTorque * factor;
609
  end;
610
end;
611

612
// MirrorTranslation
613

614
procedure TGLBInertia.MirrorTranslation;
615
begin
616
  FTranslationSpeed.Invert;
617
end;
618

619
// SurfaceBounce
620

621
procedure TGLBInertia.SurfaceBounce(const surfaceNormal: TVector; restitution: single);
622
var
623
  f: single;
624
begin
625
  // does the current speed vector comply?
626
  f := VectorDotProduct(FTranslationSpeed.AsVector, surfaceNormal);
627
  if f < 0 then
628
  begin
629
    // remove the non-complying part of the speed vector
630
    FTranslationSpeed.AddScaledVector(-f / VectorNorm(surfaceNormal) *
631
      (1 + restitution), surfaceNormal);
632
  end;
633
end;
634

635
// ------------------
636
// ------------------ TGLBAcceleration ------------------
637
// ------------------
638

639
// Create
640

641
constructor TGLBAcceleration.Create(aOwner: TGLXCollection);
642
begin
643
  inherited;
644
  if aOwner <> nil then
645
    if not (csReading in TComponent(aOwner.Owner).ComponentState) then
646
      GetOrCreateInertia(TGLBehaviours(aOwner));
647
  FAcceleration := TGLCoordinates.CreateInitialized(Self, NullHmgVector, csVector);
648
end;
649

650
// Destroy
651

652
destructor TGLBAcceleration.Destroy;
653
begin
654
  inherited;
655
  FAcceleration.Free;
656
end;
657

658
 
659

660
procedure TGLBAcceleration.Assign(Source: TPersistent);
661
begin
662
  if Source.ClassType = Self.ClassType then
663
  begin
664
    FAcceleration.Assign(TGLBAcceleration(Source).FAcceleration);
665
  end;
666
  inherited Assign(Source);
667
end;
668

669
// WriteToFiler
670

671
procedure TGLBAcceleration.WriteToFiler(writer: TWriter);
672
begin
673
  inherited;
674
  with writer do
675
  begin
676
    WriteInteger(0); // Archive Version 0
677
    FAcceleration.WriteToFiler(writer);
678
  end;
679
end;
680

681
// ReadFromFiler
682

683
procedure TGLBAcceleration.ReadFromFiler(reader: TReader);
684
begin
685
  inherited;
686
  with reader do
687
  begin
688
    ReadInteger; // ignore archiveVersion
689
    FAcceleration.ReadFromFiler(reader);
690
  end;
691
end;
692

693
// SetAcceleration
694

695
procedure TGLBAcceleration.SetAcceleration(const val: TGLCoordinates);
696
begin
697
  FAcceleration.Assign(val);
698
end;
699

700
 
701

702
class function TGLBAcceleration.FriendlyName: string;
703
begin
704
  Result := 'Simple Acceleration';
705
end;
706

707
// FriendlyDescription
708

709
class function TGLBAcceleration.FriendlyDescription: string;
710
begin
711
  Result := 'A simple and constant acceleration';
712
end;
713

714
// UniqueBehaviour
715

716
class function TGLBAcceleration.UniqueItem: boolean;
717
begin
718
  Result := False;
719
end;
720

721
// DoProgress
722

723
procedure TGLBAcceleration.DoProgress(const progressTime: TProgressTimes);
724
var
725
  i: integer;
726
  Inertia: TGLBInertia;
727
begin
728
  i := Owner.IndexOfClass(TGLBInertia);
729
  if i >= 0 then
730
  begin
731
    Inertia := TGLBInertia(Owner[i]);
732
    Inertia.ApplyTranslationAcceleration(progressTime.deltaTime,
733
      FAcceleration.DirectVector);
734
  end
735
  else
736
  begin
737
    TGLBInertia.Create(Owner);
738
    //on next progress event this exception won't be raised, because TGLBInertia will be created again
739
    raise Exception.Create(ClassName + ' requires ' + TGLBInertia.ClassName +
740
      '! (' + TGLBInertia.ClassName + ' was added to the Behaviours again)');
741
  end;
742
end;
743

744
// ------------------------------------------------------------------
745
// ------------------------------------------------------------------
746
// ------------------------------------------------------------------
747
initialization
748
  // ------------------------------------------------------------------
749
  // ------------------------------------------------------------------
750
  // ------------------------------------------------------------------
751

752
  // class registrations
753
  RegisterXCollectionItemClass(TGLBInertia);
754
  RegisterXCollectionItemClass(TGLBAcceleration);
755

756
finalization
757

758
  UnregisterXCollectionItemClass(TGLBInertia);
759
  UnregisterXCollectionItemClass(TGLBAcceleration);
760

761
end.
762

763

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.